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 14:04, 21 February 2021 (flesh out title-function patching). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

local checkType = require('libraryUtil').checkType

local p = {}
local mockTitleRegistry = {}

--[[
-- Patch an existing title object with the given options.
--]]
function p.patchTitleObject(title, options)
	-- Set protection levels
	local levels = {
		edit = {},
		move = {},
		autoreview = {}
	}
	for _, action in ipairs{'edit', 'move', 'autoreview'} do
		local level = options[action]
		if level then
			levels[action][1] = level
		end
	end
	rawset(title, 'protectionLevels', levels)

	-- Set content model
	rawset(title, 'contentModel', options.contentModel or 'wikitext')

	return title
end

--[[
-- Construct a new mock title.
--]]
function p.MockTitle(options)
	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

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 mw.title.%s(%s)", funcName, table.concat({...}, ", ")))
		end
		local mockTitle = mockTitleRegistry[title.prefixedText]
		if mockTitle then
			return mockTitle
		else
			return title
		end
	end
	return oldTitleNew
end

function p.patchTitleNew(func, ...)
	local oldTitleNew = patchTitleFunc("new")
	func(...)
	mw.title.new = oldTitleNew
end

function p.patchMakeTitle(func, ...)
	local oldMakeTitle = patchTitleFunc("makeTitle")
	func(...)
	mw.title.makeTitle = oldMakeTitle
end

function p.patchTitleConstructors(func, ...)
	local oldTitleNew = patchTitleFunc("new")
	local oldMakeTitle = patchTitleFunc("makeTitle")
	func(...)
	mw.title.new = oldTitleNew
	mw.title.makeTitle = oldMakeTitle
end

return p