<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3AMock_title</id>
	<title>Module:Mock title - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3AMock_title"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Mock_title&amp;action=history"/>
	<updated>2026-05-27T11:21:58Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Mock_title&amp;diff=143985&amp;oldid=prev</id>
		<title>imported&gt;Mr. Stradivarius: simplify file property code</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Mock_title&amp;diff=143985&amp;oldid=prev"/>
		<updated>2021-05-22T06:23:07Z</updated>

		<summary type="html">&lt;p&gt;simplify file property code&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local checkType = require(&amp;#039;libraryUtil&amp;#039;).checkType&lt;br /&gt;
local mRepr = require(&amp;#039;Module:Repr&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
local mockTitleRegistry = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Capitalize a string.&lt;br /&gt;
--]]&lt;br /&gt;
local function capitalize(s)&lt;br /&gt;
	return s:sub(1, 1):upper() .. s:sub(2, -1)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Check that a named argument is one of multiple types.&lt;br /&gt;
--]]&lt;br /&gt;
local function checkTypeForNamedArgMulti(name, argName, arg, expectTypes)&lt;br /&gt;
	local argType = type(arg)&lt;br /&gt;
	for _, expectedType in ipairs(expectTypes) do&lt;br /&gt;
		if argType == expectedType then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	error(&lt;br /&gt;
		string.format(&lt;br /&gt;
			&amp;quot;bad named argument %s to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;,&lt;br /&gt;
			argName,&lt;br /&gt;
			name,&lt;br /&gt;
			mw.text.listToText(expectTypes, &amp;quot;, &amp;quot;, &amp;quot; or &amp;quot;),&lt;br /&gt;
			argType&lt;br /&gt;
		),&lt;br /&gt;
		3&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Set a property on an object to the given value, if that value is not nil.&lt;br /&gt;
--]]&lt;br /&gt;
local function maybeSetProperty(object, property, value)&lt;br /&gt;
	if value ~= nil then&lt;br /&gt;
		rawset(object, property, value)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Construct a mock title from a string, an ID or an options table. If we were&lt;br /&gt;
-- passed a mock title object to start with, return it as-is.&lt;br /&gt;
--]]&lt;br /&gt;
local function constructMockTitle(titleOrOptions)&lt;br /&gt;
	if titleOrOptions == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local titleOrOptionsType = type(titleOrOptions)&lt;br /&gt;
	if titleOrOptionsType == &amp;quot;string&amp;quot; or titleOrOptionsType == &amp;quot;number&amp;quot; then&lt;br /&gt;
		return p.MockTitle{page = titleOrOptions}&lt;br /&gt;
	elseif titleOrOptionsType == &amp;quot;table&amp;quot; then&lt;br /&gt;
		if type(titleOrOptions.getContent) == &amp;quot;function&amp;quot; then&lt;br /&gt;
			return titleOrOptions&lt;br /&gt;
		else&lt;br /&gt;
			return p.MockTitle(titleOrOptions)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		error(&lt;br /&gt;
			string.format(&lt;br /&gt;
				&amp;quot;Invalid type specified to constructMockTitle (expected string, number, table or nil; received %s)&amp;quot;,&lt;br /&gt;
				titleOrOptionsType&lt;br /&gt;
			),&lt;br /&gt;
			2&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Get a table of protection levels with the levels set by the user. The&lt;br /&gt;
-- makeOptionsKey is a function that takes a protection action as an input and&lt;br /&gt;
-- gives the option table key for that action. The function returns two values:&lt;br /&gt;
-- the table of protection levels (as used by the protectionLevels and&lt;br /&gt;
-- cascadingProtection title object properties), and a boolean flag indicating&lt;br /&gt;
-- whether any protection levels were set.&lt;br /&gt;
--]]&lt;br /&gt;
local function getProtectionLevels(options, makeOptionsKey)&lt;br /&gt;
	local levels = {&lt;br /&gt;
		edit = {},&lt;br /&gt;
		move = {},&lt;br /&gt;
		create = {},&lt;br /&gt;
		upload = {},&lt;br /&gt;
	}&lt;br /&gt;
	local isSet = false&lt;br /&gt;
	for action in pairs(levels) do&lt;br /&gt;
		local level = options[makeOptionsKey(action)]&lt;br /&gt;
		if level then&lt;br /&gt;
			levels[action][1] = level&lt;br /&gt;
			isSet = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return levels, isSet&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Set protection levels&lt;br /&gt;
--]]&lt;br /&gt;
local function setProtectionLevels(title, options)&lt;br /&gt;
	local protectionLevels, isProtectionSet = getProtectionLevels(&lt;br /&gt;
		options,&lt;br /&gt;
		function (action)&lt;br /&gt;
			return action .. &amp;quot;Protection&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	)&lt;br /&gt;
	if isProtectionSet then&lt;br /&gt;
		rawset(title, &amp;quot;protectionLevels&amp;quot;, protectionLevels)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Set cascading protection&lt;br /&gt;
--]]&lt;br /&gt;
local function setCascadingProtection(title, options)&lt;br /&gt;
	local cascadingProtectionLevels, isCascadingProtectionSet = getProtectionLevels(&lt;br /&gt;
		options,&lt;br /&gt;
		function (action)&lt;br /&gt;
			return string.format(&amp;quot;cascading%sProtection&amp;quot;, capitalize(action))&lt;br /&gt;
		end&lt;br /&gt;
	)&lt;br /&gt;
	local cascadingSourcesExist = options.cascadingProtectionSources and #options.cascadingProtectionSources &amp;gt;= 1&lt;br /&gt;
	if isCascadingProtectionSet and cascadingSourcesExist then&lt;br /&gt;
		rawset(&lt;br /&gt;
			title,&lt;br /&gt;
			&amp;quot;cascadingProtection&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				restrictions = cascadingProtectionLevels,&lt;br /&gt;
				sources = options.cascadingProtectionSources,&lt;br /&gt;
			}&lt;br /&gt;
		)&lt;br /&gt;
	elseif isCascadingProtectionSet then&lt;br /&gt;
		error(&amp;quot;a cascading protection argument was given but the cascadingProtectionSources argument was missing or empty&amp;quot;, 2)&lt;br /&gt;
	elseif cascadingSourcesExist then&lt;br /&gt;
		error(&amp;quot;the cascadingProtectionSources argument was given, but no cascading protection argument was given&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Set page content, if specified&lt;br /&gt;
--]]&lt;br /&gt;
local function maybeSetContent(titleObject, content)&lt;br /&gt;
	if content then&lt;br /&gt;
		rawset(titleObject, &amp;quot;getContent&amp;quot;, function () return content end)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Set properties in the file table, as well as the fileExists property&lt;br /&gt;
--]]&lt;br /&gt;
local function setFileProperties(title, options)&lt;br /&gt;
	if title.file then&lt;br /&gt;
		for _, property in ipairs{&amp;quot;exists&amp;quot;, &amp;quot;width&amp;quot;, &amp;quot;height&amp;quot;, &amp;quot;pages&amp;quot;, &amp;quot;size&amp;quot;, &amp;quot;mimeType&amp;quot;, &amp;quot;length&amp;quot;} do&lt;br /&gt;
			local optionName = &amp;quot;file&amp;quot; .. capitalize(property)&lt;br /&gt;
			maybeSetProperty(title.file, property, options[optionName])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Patch an existing title object with the given options.&lt;br /&gt;
--]]&lt;br /&gt;
function p.patchTitleObject(title, options)&lt;br /&gt;
	-- Set simple properties&lt;br /&gt;
	for _, property in ipairs{&amp;quot;id&amp;quot;, &amp;quot;isRedirect&amp;quot;, &amp;quot;exists&amp;quot;, &amp;quot;contentModel&amp;quot;} do&lt;br /&gt;
		maybeSetProperty(title, property, options[property])&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Set redirect title&lt;br /&gt;
	maybeSetProperty(title, &amp;quot;redirectTarget&amp;quot;, constructMockTitle(options.redirectTarget))&lt;br /&gt;
	&lt;br /&gt;
	-- Set complex properties&lt;br /&gt;
	setProtectionLevels(title, options)&lt;br /&gt;
	setCascadingProtection(title, options)&lt;br /&gt;
	maybeSetContent(title, options.content)&lt;br /&gt;
	setFileProperties(title, options)&lt;br /&gt;
	&lt;br /&gt;
	return title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Construct a new mock title.&lt;br /&gt;
--]]&lt;br /&gt;
function p.MockTitle(options)&lt;br /&gt;
	checkType(&amp;quot;MockTitle&amp;quot;, 1, options, &amp;quot;table&amp;quot;)&lt;br /&gt;
	checkTypeForNamedArgMulti(&amp;quot;MockTitle&amp;quot;, &amp;quot;page&amp;quot;, options.page, {&amp;quot;string&amp;quot;, &amp;quot;number&amp;quot;})&lt;br /&gt;
	local title = mw.title.new(options.page)&lt;br /&gt;
	return p.patchTitleObject(title, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Register a mock title.&lt;br /&gt;
-- This can be a string, a mock title object or a table of options for&lt;br /&gt;
-- MockTitle.&lt;br /&gt;
--]]&lt;br /&gt;
function p.registerMockTitle(titleOrOptions)&lt;br /&gt;
	checkType(&amp;quot;registerMockTitle&amp;quot;, 1, titleOrOptions, &amp;quot;table&amp;quot;)&lt;br /&gt;
	title = constructMockTitle(titleOrOptions)&lt;br /&gt;
	mockTitleRegistry[title.prefixedText] = title&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Remove a title from the mock title registry.&lt;br /&gt;
-- Returns the title that was removed.&lt;br /&gt;
--]]&lt;br /&gt;
function p.deregisterMockTitle(titleOrOptions)&lt;br /&gt;
	checkType(&amp;quot;deregisterMockTitle&amp;quot;, 1, title, &amp;quot;table&amp;quot;)&lt;br /&gt;
	title = constructMockTitle(titleOrOptions)&lt;br /&gt;
	registeredTitle = mockTitleRegistry[title.prefixedText]&lt;br /&gt;
	mockTitleRegistry[title.prefixedText] = nil&lt;br /&gt;
	return registeredTitle&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Register multiple mock titles.&lt;br /&gt;
--]]&lt;br /&gt;
function p.registerMockTitles(...)&lt;br /&gt;
	checkType(&amp;quot;registerMockTitles&amp;quot;, 1, titleData, &amp;quot;table&amp;quot;)&lt;br /&gt;
	for _, titleOrOptions in ipairs{...} do&lt;br /&gt;
		p.registerMockTitle(titleOrOptions)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Deregister multiple mock titles.&lt;br /&gt;
-- Returns a sequence of titles that were removed.&lt;br /&gt;
--]]&lt;br /&gt;
function p.deregisterMockTitles(...)&lt;br /&gt;
	checkType(&amp;quot;deregisterMockTitles&amp;quot;, 1, titleData, &amp;quot;table&amp;quot;)&lt;br /&gt;
	local removedTitles = {}&lt;br /&gt;
	for _, titleOrOptions in ipairs{...} do&lt;br /&gt;
		table.insert(removedTitles, p.deregisterMockTitle(titleOrOptions))&lt;br /&gt;
	end&lt;br /&gt;
	return removedTitles&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Clear the mock title registry.&lt;br /&gt;
--]]&lt;br /&gt;
function p.clearMockTitleRegistry()&lt;br /&gt;
	mockTitleRegistry = {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Patch the given title function.&lt;br /&gt;
-- This replaces the title function with a function that looks in the title&lt;br /&gt;
-- registry for the given title.&lt;br /&gt;
--]]&lt;br /&gt;
local function patchTitleFunc(funcName)&lt;br /&gt;
	local oldFunc = mw.title[funcName]&lt;br /&gt;
	mw.title[funcName] = function(...)&lt;br /&gt;
		local title = oldFunc(...)&lt;br /&gt;
		if not title then&lt;br /&gt;
			error(&lt;br /&gt;
				string.format(&lt;br /&gt;
					&amp;quot;Could not make title object from invocation %s&amp;quot;,&lt;br /&gt;
					mRepr.invocationRepr{&lt;br /&gt;
						funcName = &amp;quot;mw.title.&amp;quot; .. funcName,&lt;br /&gt;
						args = {...}&lt;br /&gt;
					}&lt;br /&gt;
				),&lt;br /&gt;
				2&lt;br /&gt;
			)&lt;br /&gt;
		end&lt;br /&gt;
		local mockTitle = mockTitleRegistry[title.prefixedText]&lt;br /&gt;
		if mockTitle then&lt;br /&gt;
			return mockTitle&lt;br /&gt;
		else&lt;br /&gt;
			return title&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return oldTitleNew&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Patch mw.title.new.&lt;br /&gt;
-- The original mw.title.new is restored after running the given function.&lt;br /&gt;
--]]&lt;br /&gt;
function p.patchTitleNew(func, ...)&lt;br /&gt;
	local oldTitleNew = patchTitleFunc(&amp;quot;new&amp;quot;)&lt;br /&gt;
	func(...)&lt;br /&gt;
	mw.title.new = oldTitleNew&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Patch mw.title.makeTitle.&lt;br /&gt;
-- The original mw.title.makeTitle is restored after running the given function.&lt;br /&gt;
--]]&lt;br /&gt;
function p.patchMakeTitle(func, ...)&lt;br /&gt;
	local oldMakeTitle = patchTitleFunc(&amp;quot;makeTitle&amp;quot;)&lt;br /&gt;
	func(...)&lt;br /&gt;
	mw.title.makeTitle = oldMakeTitle&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Patch mw.title.new and mw.title.makeTitle.&lt;br /&gt;
-- The original title functions are restored after running the given function.&lt;br /&gt;
--]]&lt;br /&gt;
function p.patchTitleConstructors(func, ...)&lt;br /&gt;
	local oldTitleNew = patchTitleFunc(&amp;quot;new&amp;quot;)&lt;br /&gt;
	local oldMakeTitle = patchTitleFunc(&amp;quot;makeTitle&amp;quot;)&lt;br /&gt;
	func(...)&lt;br /&gt;
	mw.title.new = oldTitleNew&lt;br /&gt;
	mw.title.makeTitle = oldMakeTitle&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Mr. Stradivarius</name></author>
	</entry>
</feed>