右眼跳是什么预兆| animals什么意思| 脑宁又叫什么名字| o型血可以接受什么血型| ex是什么| 什么牌奶粉好| dha中文叫什么| 纹身有什么危害| 什么牛不吃草| 石头记为什么叫红楼梦| 为什么无缘无故流鼻血| 夏天喝什么好| 秋天是什么样子的| 高血压挂号要挂什么科| 颈椎病挂什么科最好| 石榴代表什么生肖| 喝酒后胃不舒服吃什么药| 15度穿什么衣服合适| 生理期提前是什么原因| 九月份有什么节日| 经常流鼻涕是什么原因| 胰腺炎是什么病严重吗| 鸽子喜欢吃什么食物| 低回声团是什么意思| 白舌苔很厚是什么病症| 白油是什么| 氟比洛芬是什么药| 什么车最长脑筋急转弯| c5是什么驾驶证| 摩什么擦什么| 为什么突然有狐臭了| 什么是钙化灶| 冠状沟有白色分泌物是什么原因| 气血不足吃什么| 视力模糊什么原因| 梅花鹿吃什么食物| 口臭用什么药| 受孕是什么意思| 肝内胆管结石是什么意思| 子宫癌是什么症状| 雍正为什么不杀十阿哥| 公明仪属什么生肖| 66年属马是什么命| 泌尿外科是看什么的| 五百年前是什么朝代| 缘分什么意思| prn是什么医嘱| 眉毛尾部有痣代表什么| 经常手瘾吃什么药| 日午念什么| 四月十八日是什么日子| 鸡胸是什么原因引起的| 结婚下大雨是什么兆头| 贾琏为什么叫二爷| 斐然是什么意思| 虫咬性皮炎用什么药| 男人蛋蛋疼是什么原因| 稀奶油可以做什么| 三省吾身是什么意思| 又什么又什么的葡萄| 甘油三酯高用什么药好| 苹果代表什么生肖| 生灵涂炭是什么意思| 奇的多音字是什么| 零和博弈是什么意思| 什么叫做红颜知己| 宝宝病毒性感冒吃什么药效果好| 脖子痛什么原因引起的| 肺部有问题一般会出现什么症状| 胃炎是什么症状| 做核磁共振需要注意什么| 微信被拉黑后显示什么| 什么属相不能摆放大象| 补水什么意思| id是什么意思的缩写| 什么叫前列腺| 痛风吃什么药好| 工装是什么| 汗毛重是什么原因| 政协是干什么的| 眼袋是什么原因造成的| 梦见梅花鹿是什么预兆| 旧历是什么意思| 钠对人体有什么作用| 菠菜是什么季节的菜| 肚子胀气放屁吃什么药| 脾五行属什么| 月季花是什么颜色| 辟谣是什么意思| 角的大小和什么有关| 树挪死人挪活是什么意思| 钠低吃什么| cta是什么意思| 真丝香云纱是什么面料| 心慌挂什么科| 更是什么结构的字| 重阳节是干什么的| 什么物流寄大件便宜| 部长助理是什么级别| 前列腺在哪里男人的什么部位| 钢铁侠叫什么名字| 菊花和什么一起泡最好| 肌张力高对宝宝有什么影响| 瑜伽垫什么材质的好| 杜仲泡水喝有什么功效| 56年属什么生肖| 谷草谷丙偏低代表什么| 夏天为什么会感冒| 什么病会引起腰疼| 金蝉脱壳是什么意思| 山竹吃了有什么好处| 逸搏心律什么意思| 杨桃有什么营养价值| o型血和b型血的孩子是什么血型| 草酸钙结晶是什么意思| 榴莲为什么会苦| 惊什么失什么| 口甘读什么| 四大发明是什么| 梦见死去的朋友是什么意思| 为什么打哈欠会传染| 5月30是什么星座| 氟骨症是什么病| 心气虚吃什么中成药| 银925是什么意思| 真实是什么意思| 仙人掌有什么作用| 欲加之罪何患无辞是什么意思| 王五行属性是什么| kitchen什么意思| 蜈蚣最怕什么东西| 做脑部ct挂什么科| 什么是双向抑郁| 沉默是什么意思| 什么样的月亮| 卡马西平片治什么病| 睚眦欲裂什么意思| 大暑是什么意思啊| 高考推迟月经吃什么药| 肥宅是什么意思| 丙申五行属什么| 独什么心什么| 和田玉对身体有什么好处| 晚饭后散步有什么好处| 人中浅的女人代表什么| 精索静脉曲张什么症状| edm是什么意思| 脑供血不足用什么药| 什么品种荔枝最好吃| 说话不清楚是什么原因导致的| 藿香正气水什么人不能喝| 2029年属什么生肖| 吃什么东西可以除湿气| 做爱都有什么姿势| 沉香有什么作用| 什么是ct检查| 乌鸡白凤丸适合什么人吃| 嘻哈是什么意思| 局级是什么级别| 贼眉鼠眼是什么生肖| 类风湿关节炎吃什么药| 补铁有什么好处| 沙悟净的武器叫什么| 干眼症是什么| 蜱虫是什么虫| 三季人是什么意思| 剔除是什么意思| pp1是什么意思| 孝服是什么意思| pass掉是什么意思| 陨石有什么作用和功效| 上传下达什么意思| 太阳是一颗什么星| 6月11号是什么星座| 转氨酶高吃什么药| 文盲是什么意思| 肺部散在小结节是什么意思| 嘴唇发黑是什么原因引起的| 梦见好多羊是什么意思| 免职是什么意思| 人出汗多是什么原因| 为什么腰疼| 阿尔茨海默病吃什么药| 梦到别人给钱是什么意思| 心脏彩超能检查出什么| 什么人生病从来不看医生| 什么地腐烂| 淡竹叶有什么功效| 小圆细胞阳性什么意思| 炼乳是什么东西| 猪肝有什么功效| 来月经前头痛什么原因| 嗣女是什么意思| 什么什么斑斓| 甲状腺球蛋白高是什么原因| 沙果是什么水果| 送向日葵代表什么意思| 97年什么命| 胸闷气短可能是什么病| 一进门见到什么植物好| ra是什么病的缩写| 书生是什么意思| 增加性功能吃什么药| 糖蛋白是什么| 撸铁是什么意思| 灌肠是什么意思| 做月子吃什么菜| 体面什么意思| 左肾小结石是什么意思| 内分泌紊乱有什么症状表现| 金牛座女和什么星座最配| 娘酒是什么酒| 不宁腿综合症是什么原因引起的| 汗液里面有什么成分| 豹子号是什么意思| 肾主骨是什么意思| 希思黎属于什么档次| 纪委书记是什么级别| 炸了是什么意思| 牛子是什么意思| 胸部胀痛什么原因| 生水是什么意思| 男人吃六味地黄丸有什么好处| 跑完步头疼是为什么| 一晚上尿五六次是什么原因| 产前筛查是检查什么| 咳嗽吐白痰是什么病| 不以为然是什么意思| 压迫感是什么意思| 尿道痒男吃什么消炎药| b族维生素是什么意思| bf是什么| 头不舒服是什么原因| 衣冠禽兽什么意思| 眼眶疼是什么原因| 218是什么意思| 肌酐为什么会升高| 肺坠积性改变什么意思| 儿童抽动症挂什么科| 什么人容易得帕金森病| 雅丹是什么意思| 尿道口有灼热感是什么原因| 血管痉挛是什么原因引起的| 喝椰子粉有什么好处| 姜黄与生姜有什么区别| 智齿拔了有什么影响| 柠檬水有什么功效| 元宵节送什么| 狮子座是什么象星座| 黑色的鸟是什么鸟| 小孩老咳嗽是什么原因| 猫离家出走预示着什么| gb10769是什么标准| 什么是心衰| 剪不断理还乱什么意思| 畸胎瘤是什么病| 金牛男喜欢什么样的女生| 电脑什么时候发明的| 鱼生是什么鱼| 漫山遍野是什么意思| 宫颈囊肿是什么意思| 心不在焉是什么意思| 绿巨人是什么意思| 投影是什么意思| 百度Jump to content

走路脚后跟疼是什么原因

Permanently protected module
From Wikipedia, the free encyclopedia
This is the current revision of this page, as edited by SilverLocust (talk | contribs) at 17:58, 19 March 2025 (fix for mobile and search issue, see talk page). The present address (URL) is a permanent link to this version.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

-- This module implements {{pp-meta}} and its daughter templates such as
-- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.

-- Initialise necessary modules.
require('strict')
local makeFileLink = require('Module:File link')._main
local effectiveProtectionLevel = require('Module:Effective protection level')._main
local effectiveProtectionExpiry = require('Module:Effective protection expiry')._main
local yesno = require('Module:Yesno')

-- Lazily initialise modules and objects we don't always need.
local getArgs, makeMessageBox, lang

-- Set constants.
local CONFIG_MODULE = 'Module:Protection banner/config'

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

local function makeCategoryLink(cat, sort)
	if cat then
		return string.format(
			'[[%s:%s|%s]]',
			mw.site.namespaces[14].name,
			cat,
			sort
		)
	end
end

-- Validation function for the expiry and the protection date
local function validateDate(dateString, dateType)
	if not lang then
		lang = mw.language.getContentLanguage()
	end
	local success, result = pcall(lang.formatDate, lang, 'U', dateString)
	if success then
		result = tonumber(result)
		if result then
			return result
		end
	end
	error(string.format(
		'invalid %s: %s',
		dateType,
		tostring(dateString)
	), 4)
end

local function makeFullUrl(page, query, display)
	return string.format(
		'[%s %s]',
		tostring(mw.uri.fullUrl(page, query)),
		display
	)
end

-- Given a directed graph formatted as node -> table of direct successors,
-- get a table of all nodes reachable from a given node (though always
-- including the given node).
local function getReachableNodes(graph, start)
	local toWalk, retval = {[start] = true}, {}
	while true do
		-- Can't use pairs() since we're adding and removing things as we're iterating
		local k = next(toWalk) -- This always gets the "first" key
		if k == nil then
			return retval
		end
		toWalk[k] = nil
		retval[k] = true
		for _,v in ipairs(graph[k]) do
			if not retval[v] then
				toWalk[v] = true
			end
		end
	end
end

--------------------------------------------------------------------------------
-- Protection class
--------------------------------------------------------------------------------

local Protection = {}
Protection.__index = Protection

Protection.supportedActions = {
	edit = true,
	move = true,
	autoreview = true,
	upload = true
}

Protection.bannerConfigFields = {
	'text',
	'explanation',
	'tooltip',
	'alt',
	'link',
	'image'
}

function Protection.new(args, cfg, title)
	local obj = {}
	obj._cfg = cfg
	obj.title = title or mw.title.getCurrentTitle()

	-- Set action
	if not args.action then
		obj.action = 'edit'
	elseif Protection.supportedActions[args.action] then
		obj.action = args.action
	else
		error(string.format(
			'invalid action: %s',
			tostring(args.action)
		), 3)
	end

	-- Set level
	obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)
	if not obj.level or (obj.action == 'move' and obj.level == 'autoconfirmed') then
		-- Users need to be autoconfirmed to move pages anyway, so treat
		-- semi-move-protected pages as unprotected.
		obj.level = '*'
	end

	-- Set expiry
	local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title)
	if effectiveExpiry == 'infinity' then
		obj.expiry = 'indef'
	elseif effectiveExpiry ~= 'unknown' then
		obj.expiry = validateDate(effectiveExpiry, 'expiry date')
	end

	-- Set reason
	if args[1] then
		obj.reason = mw.ustring.lower(args[1])
		if obj.reason:find('|') then
			error('reasons cannot contain the pipe character ("|")', 3)
		end
	end

	-- Set protection date
	if args.date then
		obj.protectionDate = validateDate(args.date, 'protection date')
	end
	
	-- Set banner config
	do
		obj.bannerConfig = {}
		local configTables = {}
		if cfg.banners[obj.action] then
			configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason]
		end
		if cfg.defaultBanners[obj.action] then
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level]
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default
		end
		configTables[#configTables + 1] = cfg.masterBanner
		for i, field in ipairs(Protection.bannerConfigFields) do
			for j, t in ipairs(configTables) do
				if t[field] then
					obj.bannerConfig[field] = t[field]
					break
				end
			end
		end
	end
	return setmetatable(obj, Protection)
end

function Protection:isUserScript()
	-- Whether the page is a user JavaScript or CSS page.
	local title = self.title
	return title.namespace == 2 and (
		title.contentModel == 'javascript' or title.contentModel == 'css'
	)
end

function Protection:isProtected()
	return self.level ~= '*'
end

function Protection:shouldShowLock()
	-- Whether we should output a banner/padlock
	return self:isProtected() and not self:isUserScript()
end

-- Whether this page needs a protection category.
Protection.shouldHaveProtectionCategory = Protection.shouldShowLock

function Protection:isTemporary()
	return type(self.expiry) == 'number'
end

function Protection:makeProtectionCategory()
	if not self:shouldHaveProtectionCategory() then
		return ''
	end

	local cfg = self._cfg
	local title = self.title
	
	-- Get the expiry key fragment.
	local expiryFragment
	if self.expiry == 'indef' then
		expiryFragment = self.expiry
	elseif type(self.expiry) == 'number' then
		expiryFragment = 'temp'
	end

	-- Get the namespace key fragment.
	local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]
	if not namespaceFragment and title.namespace % 2 == 1 then
			namespaceFragment = 'talk'
	end

	-- Define the order that key fragments are tested in. This is done with an
	-- array of tables containing the value to be tested, along with its
	-- position in the cfg.protectionCategories table.
	local order = {
		{val = expiryFragment,    keypos = 1},
		{val = namespaceFragment, keypos = 2},
		{val = self.reason,       keypos = 3},
		{val = self.level,        keypos = 4},
		{val = self.action,       keypos = 5}
	}

	--[[
	-- The old protection templates used an ad-hoc protection category system,
	-- with some templates prioritising namespaces in their categories, and
	-- others prioritising the protection reason. To emulate this in this module
	-- we use the config table cfg.reasonsWithNamespacePriority to set the
	-- reasons for which namespaces have priority over protection reason.
	-- If we are dealing with one of those reasons, move the namespace table to
	-- the end of the order table, i.e. give it highest priority. If not, the
	-- reason should have highest priority, so move that to the end of the table
	-- instead.
	--]]
	table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3))
 
	--[[
	-- Define the attempt order. Inactive subtables (subtables with nil "value"
	-- fields) are moved to the end, where they will later be given the key
	-- "all". This is to cut down on the number of table lookups in
	-- cfg.protectionCategories, which grows exponentially with the number of
	-- non-nil keys. We keep track of the number of active subtables with the
	-- noActive parameter.
	--]]
	local noActive, attemptOrder
	do
		local active, inactive = {}, {}
		for i, t in ipairs(order) do
			if t.val then
				active[#active + 1] = t
			else
				inactive[#inactive + 1] = t
			end
		end
		noActive = #active
		attemptOrder = active
		for i, t in ipairs(inactive) do
			attemptOrder[#attemptOrder + 1] = t
		end
	end
 
	--[[
	-- Check increasingly generic key combinations until we find a match. If a
	-- specific category exists for the combination of key fragments we are
	-- given, that match will be found first. If not, we keep trying different
	-- key fragment combinations until we match using the key
	-- "all-all-all-all-all".
	--
	-- To generate the keys, we index the key subtables using a binary matrix
	-- with indexes i and j. j is only calculated up to the number of active
	-- subtables. For example, if there were three active subtables, the matrix
	-- would look like this, with 0 corresponding to the key fragment "all", and
	-- 1 corresponding to other key fragments.
	-- 
	--   j 1  2  3
	-- i  
	-- 1   1  1  1
	-- 2   0  1  1
	-- 3   1  0  1
	-- 4   0  0  1
	-- 5   1  1  0
	-- 6   0  1  0
	-- 7   1  0  0
	-- 8   0  0  0
	-- 
	-- Values of j higher than the number of active subtables are set
	-- to the string "all".
	--
	-- A key for cfg.protectionCategories is constructed for each value of i.
	-- The position of the value in the key is determined by the keypos field in
	-- each subtable.
	--]]
	local cats = cfg.protectionCategories
	for i = 1, 2^noActive do
		local key = {}
		for j, t in ipairs(attemptOrder) do
			if j > noActive then
				key[t.keypos] = 'all'
			else
				local quotient = i / 2 ^ (j - 1)
				quotient = math.ceil(quotient)
				if quotient % 2 == 1 then
					key[t.keypos] = t.val
				else
					key[t.keypos] = 'all'
				end
			end
		end
		key = table.concat(key, '|')
		local attempt = cats[key]
		if attempt then
			return makeCategoryLink(attempt, title.text)
		end
	end
	return ''
end

function Protection:isIncorrect()
	local expiry = self.expiry
	return not self:shouldHaveProtectionCategory()
		or type(expiry) == 'number' and expiry < os.time()
end

function Protection:isTemplateProtectedNonTemplate()
	local action, namespace = self.action, self.title.namespace
	return self.level == 'templateeditor'
		and (
			(action ~= 'edit' and action ~= 'move')
			or (namespace ~= 10 and namespace ~= 828)
		)
end

function Protection:makeCategoryLinks()
	local msg = self._cfg.msg
	local ret = {self:makeProtectionCategory()}
	if self:isIncorrect() then
		ret[#ret + 1] = makeCategoryLink(
			msg['tracking-category-incorrect'],
			self.title.text
		)
	end
	if self:isTemplateProtectedNonTemplate() then
		ret[#ret + 1] = makeCategoryLink(
			msg['tracking-category-template'],
			self.title.text
		)
	end
	return table.concat(ret)
end

--------------------------------------------------------------------------------
-- Blurb class
--------------------------------------------------------------------------------

local Blurb = {}
Blurb.__index = Blurb

Blurb.bannerTextFields = {
	text = true,
	explanation = true,
	tooltip = true,
	alt = true,
	link = true
}

function Blurb.new(protectionObj, args, cfg)
	return setmetatable({
		_cfg = cfg,
		_protectionObj = protectionObj,
		_args = args
	}, Blurb)
end

-- Private methods --

function Blurb:_formatDate(num)
	-- Formats a Unix timestamp into dd Month, YYYY format.
	lang = lang or mw.language.getContentLanguage()
	local success, date = pcall(
		lang.formatDate,
		lang,
		self._cfg.msg['expiry-date-format'] or 'j F Y',
		'@' .. tostring(num)
	)
	if success then
		return date
	end
end

function Blurb:_getExpandedMessage(msgKey)
	return self:_substituteParameters(self._cfg.msg[msgKey])
end

function Blurb:_substituteParameters(msg)
	if not self._params then
		local parameterFuncs = {}

		parameterFuncs.CURRENTVERSION     = self._makeCurrentVersionParameter
		parameterFuncs.EDITREQUEST        = self._makeEditRequestParameter
		parameterFuncs.EXPIRY             = self._makeExpiryParameter
		parameterFuncs.EXPLANATIONBLURB   = self._makeExplanationBlurbParameter
		parameterFuncs.IMAGELINK          = self._makeImageLinkParameter
		parameterFuncs.INTROBLURB         = self._makeIntroBlurbParameter
		parameterFuncs.INTROFRAGMENT      = self._makeIntroFragmentParameter
		parameterFuncs.PAGETYPE           = self._makePagetypeParameter
		parameterFuncs.PROTECTIONBLURB    = self._makeProtectionBlurbParameter
		parameterFuncs.PROTECTIONDATE     = self._makeProtectionDateParameter
		parameterFuncs.PROTECTIONLEVEL    = self._makeProtectionLevelParameter
		parameterFuncs.PROTECTIONLOG      = self._makeProtectionLogParameter
		parameterFuncs.TALKPAGE           = self._makeTalkPageParameter
		parameterFuncs.TOOLTIPBLURB       = self._makeTooltipBlurbParameter
		parameterFuncs.TOOLTIPFRAGMENT    = self._makeTooltipFragmentParameter
		parameterFuncs.VANDAL             = self._makeVandalTemplateParameter
		
		self._params = setmetatable({}, {
			__index = function (t, k)
				local param
				if parameterFuncs[k] then
					param = parameterFuncs[k](self)
				end
				param = param or ''
				t[k] = param
				return param
			end
		})
	end
	
	msg = msg:gsub('${(%u+)}', self._params)
	return msg
end

function Blurb:_makeCurrentVersionParameter()
	-- A link to the page history or the move log, depending on the kind of
	-- protection.
	local pagename = self._protectionObj.title.prefixedText
	if self._protectionObj.action == 'move' then
		-- We need the move log link.
		return makeFullUrl(
			'Special:Log',
			{type = 'move', page = pagename},
			self:_getExpandedMessage('current-version-move-display')
		)
	else
		-- We need the history link.
		return makeFullUrl(
			pagename,
			{action = 'history'},
			self:_getExpandedMessage('current-version-edit-display')
		)
	end
end

function Blurb:_makeEditRequestParameter()
	local mEditRequest = require('Module:Submit an edit request')
	local action = self._protectionObj.action
	local level = self._protectionObj.level
	
	-- Get the edit request type.
	local requestType
	if action == 'edit' then
		if level == 'autoconfirmed' then
			requestType = 'semi'
		elseif level == 'extendedconfirmed' then
			requestType = 'extended'
		elseif level == 'templateeditor' then
			requestType = 'template'
		end
	end
	requestType = requestType or 'full'
	
	-- Get the display value.
	local display = self:_getExpandedMessage('edit-request-display')

	return mEditRequest._link{type = requestType, display = display}
end

function Blurb:_makeExpiryParameter()
	local expiry = self._protectionObj.expiry
	if type(expiry) == 'number' then
		return self:_formatDate(expiry)
	else
		return expiry
	end
end

function Blurb:_makeExplanationBlurbParameter()
	-- Cover special cases first.
	if self._protectionObj.title.namespace == 8 then
		-- MediaWiki namespace
		return self:_getExpandedMessage('explanation-blurb-nounprotect')
	end

	-- Get explanation blurb table keys
	local action = self._protectionObj.action
	local level = self._protectionObj.level
	local talkKey = self._protectionObj.title.isTalkPage and 'talk' or 'subject'

	-- Find the message in the explanation blurb table and substitute any
	-- parameters.
	local explanations = self._cfg.explanationBlurbs
	local msg
	if explanations[action][level] and explanations[action][level][talkKey] then
		msg = explanations[action][level][talkKey]
	elseif explanations[action][level] and explanations[action][level].default then
		msg = explanations[action][level].default
	elseif explanations[action].default and explanations[action].default[talkKey] then
		msg = explanations[action].default[talkKey]
	elseif explanations[action].default and explanations[action].default.default then
		msg = explanations[action].default.default
	else
		error(string.format(
			'could not find explanation blurb for action "%s", level "%s" and talk key "%s"',
			action,
			level,
			talkKey
		), 8)
	end
	return self:_substituteParameters(msg)
end

function Blurb:_makeImageLinkParameter()
	local imageLinks = self._cfg.imageLinks
	local action = self._protectionObj.action
	local level = self._protectionObj.level
	local msg
	if imageLinks[action][level] then
		msg = imageLinks[action][level]
	elseif imageLinks[action].default then
		msg = imageLinks[action].default
	else
		msg = imageLinks.edit.default
	end
	return self:_substituteParameters(msg)
end

function Blurb:_makeIntroBlurbParameter()
	if self._protectionObj:isTemporary() then
		return self:_getExpandedMessage('intro-blurb-expiry')
	else
		return self:_getExpandedMessage('intro-blurb-noexpiry')
	end
end

function Blurb:_makeIntroFragmentParameter()
	if self._protectionObj:isTemporary() then
		return self:_getExpandedMessage('intro-fragment-expiry')
	else
		return self:_getExpandedMessage('intro-fragment-noexpiry')
	end
end

function Blurb:_makePagetypeParameter()
	local pagetypes = self._cfg.pagetypes
	return pagetypes[self._protectionObj.title.namespace]
		or pagetypes.default
		or error('no default pagetype defined', 8)
end

function Blurb:_makeProtectionBlurbParameter()
	local protectionBlurbs = self._cfg.protectionBlurbs
	local action = self._protectionObj.action
	local level = self._protectionObj.level
	local msg
	if protectionBlurbs[action][level] then
		msg = protectionBlurbs[action][level]
	elseif protectionBlurbs[action].default then
		msg = protectionBlurbs[action].default
	elseif protectionBlurbs.edit.default then
		msg = protectionBlurbs.edit.default
	else
		error('no protection blurb defined for protectionBlurbs.edit.default', 8)
	end
	return self:_substituteParameters(msg)
end

function Blurb:_makeProtectionDateParameter()
	local protectionDate = self._protectionObj.protectionDate
	if type(protectionDate) == 'number' then
		return self:_formatDate(protectionDate)
	else
		return protectionDate
	end
end

function Blurb:_makeProtectionLevelParameter()
	local protectionLevels = self._cfg.protectionLevels
	local action = self._protectionObj.action
	local level = self._protectionObj.level
	local msg
	if protectionLevels[action][level] then
		msg = protectionLevels[action][level]
	elseif protectionLevels[action].default then
		msg = protectionLevels[action].default
	elseif protectionLevels.edit.default then
		msg = protectionLevels.edit.default
	else
		error('no protection level defined for protectionLevels.edit.default', 8)
	end
	return self:_substituteParameters(msg)
end

function Blurb:_makeProtectionLogParameter()
	local pagename = self._protectionObj.title.prefixedText
	if self._protectionObj.action == 'autoreview' then
		-- We need the pending changes log.
		return makeFullUrl(
			'Special:Log',
			{type = 'stable', page = pagename},
			self:_getExpandedMessage('pc-log-display')
		)
	else
		-- We need the protection log.
		return makeFullUrl(
			'Special:Log',
			{type = 'protect', page = pagename},
			self:_getExpandedMessage('protection-log-display')
		)
	end
end

function Blurb:_makeTalkPageParameter()
	return string.format(
		'[[%s:%s#%s|%s]]',
		mw.site.namespaces[self._protectionObj.title.namespace].talk.name,
		self._protectionObj.title.text,
		self._args.section or 'top',
		self:_getExpandedMessage('talk-page-link-display')
	)
end

function Blurb:_makeTooltipBlurbParameter()
	if self._protectionObj:isTemporary() then
		return self:_getExpandedMessage('tooltip-blurb-expiry')
	else
		return self:_getExpandedMessage('tooltip-blurb-noexpiry')
	end
end

function Blurb:_makeTooltipFragmentParameter()
	if self._protectionObj:isTemporary() then
		return self:_getExpandedMessage('tooltip-fragment-expiry')
	else
		return self:_getExpandedMessage('tooltip-fragment-noexpiry')
	end
end

function Blurb:_makeVandalTemplateParameter()
	return mw.getCurrentFrame():expandTemplate{
		title="vandal-m",
		args={self._args.user or self._protectionObj.title.baseText}
	}
end

-- Public methods --

function Blurb:makeBannerText(key)
	-- Validate input.
	if not key or not Blurb.bannerTextFields[key] then
		error(string.format(
			'"%s" is not a valid banner config field',
			tostring(key)
		), 2)
	end

	-- Generate the text.
	local msg = self._protectionObj.bannerConfig[key]
	if type(msg) == 'string' then
		return self:_substituteParameters(msg)
	elseif type(msg) == 'function' then
		msg = msg(self._protectionObj, self._args)
		if type(msg) ~= 'string' then
			error(string.format(
				'bad output from banner config function with key "%s"'
					.. ' (expected string, got %s)',
				tostring(key),
				type(msg)
			), 4)
		end
		return self:_substituteParameters(msg)
	end
end

--------------------------------------------------------------------------------
-- BannerTemplate class
--------------------------------------------------------------------------------

local BannerTemplate = {}
BannerTemplate.__index = BannerTemplate

function BannerTemplate.new(protectionObj, cfg)
	local obj = {}
	obj._cfg = cfg

	-- Set the image filename.
	local imageFilename = protectionObj.bannerConfig.image
	if imageFilename then
		obj._imageFilename = imageFilename
	else
		-- If an image filename isn't specified explicitly in the banner config,
		-- generate it from the protection status and the namespace.
		local action = protectionObj.action
		local level = protectionObj.level
		local namespace = protectionObj.title.namespace
		local reason = protectionObj.reason
		
		-- Deal with special cases first.
		if (
			namespace == 10
			or namespace == 828
			or reason and obj._cfg.indefImageReasons[reason]
			)
			and action == 'edit'
			and level == 'sysop'
			and not protectionObj:isTemporary()
		then
			-- Fully protected modules and templates get the special red "indef"
			-- padlock.
			obj._imageFilename = obj._cfg.msg['image-filename-indef']
		else
			-- Deal with regular protection types.
			local images = obj._cfg.images
			if images[action] then
				if images[action][level] then
					obj._imageFilename = images[action][level]
				elseif images[action].default then
					obj._imageFilename = images[action].default
				end
			end
		end
	end
	return setmetatable(obj, BannerTemplate)
end

function BannerTemplate:renderImage()
	local filename = self._imageFilename
		or self._cfg.msg['image-filename-default']
		or 'Transparent.gif'
	return makeFileLink{
		file = filename,
		size = (self.imageWidth or 20) .. 'px',
		alt = self._imageAlt,
		link = self._imageLink,
		caption = self.imageCaption
	}
end

--------------------------------------------------------------------------------
-- Banner class
--------------------------------------------------------------------------------

local Banner = setmetatable({}, BannerTemplate)
Banner.__index = Banner

function Banner.new(protectionObj, blurbObj, cfg)
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
	obj.imageWidth = 40
	obj.imageCaption = blurbObj:makeBannerText('alt') -- Large banners use the alt text for the tooltip.
	obj._reasonText = blurbObj:makeBannerText('text')
	obj._explanationText = blurbObj:makeBannerText('explanation')
	obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing.
	return setmetatable(obj, Banner)
end

function Banner:__tostring()
	-- Renders the banner.
	makeMessageBox = makeMessageBox or require('Module:Message box').main
	local reasonText = self._reasonText or error('no reason text set', 2)
	local explanationText = self._explanationText
	local mbargs = {
		page = self._page,
		type = 'protection',
		image = self:renderImage(),
		text = string.format(
			"'''%s'''%s",
			reasonText,
			explanationText and '<br />' .. explanationText or ''
		)
	}
	return makeMessageBox('mbox', mbargs)
end

--------------------------------------------------------------------------------
-- Padlock class
--------------------------------------------------------------------------------

local Padlock = setmetatable({}, BannerTemplate)
Padlock.__index = Padlock

function Padlock.new(protectionObj, blurbObj, cfg)
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn't need the blurb.
	obj.imageWidth = 20
	obj.imageCaption = blurbObj:makeBannerText('tooltip')
	obj._imageAlt = blurbObj:makeBannerText('alt')
	obj._imageLink = blurbObj:makeBannerText('link')
	obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action]
		or cfg.padlockIndicatorNames.default
		or 'pp-default'
	return setmetatable(obj, Padlock)
end

function Padlock:__tostring()
	local frame = mw.getCurrentFrame()
	-- The nowiki tag helps prevent whitespace at the top of articles.
	return frame:extensionTag{name = 'nowiki'} .. frame:extensionTag{
		name = 'indicator',
		args = {name = self._indicatorName},
		content = self:renderImage()
	}
end

--------------------------------------------------------------------------------
-- Exports
--------------------------------------------------------------------------------

local p = {}

function p._exportClasses()
	-- This is used for testing purposes.
	return {
		Protection = Protection,
		Blurb = Blurb,
		BannerTemplate = BannerTemplate,
		Banner = Banner,
		Padlock = Padlock,
	}
end

function p._main(args, cfg, title)
	args = args or {}
	cfg = cfg or require(CONFIG_MODULE)

	local protectionObj = Protection.new(args, cfg, title)

	local ret = {}

	-- If a page's edit protection is equally or more restrictive than its
	-- protection from some other action, then don't bother displaying anything
	-- for the other action (except categories).
	if not yesno(args.catonly) and (protectionObj.action == 'edit' or
		args.demolevel or
		not getReachableNodes(
			cfg.hierarchy,
			protectionObj.level
		)[effectiveProtectionLevel('edit', protectionObj.title)])
	then
		-- Initialise the blurb object
		local blurbObj = Blurb.new(protectionObj, args, cfg)
	
		-- Render the banner
		if protectionObj:shouldShowLock() then
			ret[#ret + 1] = tostring(
				(yesno(args.small) and Padlock or Banner)
				.new(protectionObj, blurbObj, cfg)
			)
		end
	end

	-- Render the categories
	if yesno(args.category) ~= false then
		ret[#ret + 1] = protectionObj:makeCategoryLinks()
	end
	
	-- For arbitration enforcement, flagging [[WP:PIA]] pages to enable [[Special:AbuseFilter/1339]] to flag edits to them
	if protectionObj.level == "extendedconfirmed" then
		if require("Module:TableTools").inArray(protectionObj.title.talkPageTitle.categories, "Wikipedia pages subject to the extended confirmed restriction related to the Arab-Israeli conflict") then
			ret[#ret + 1] = "<p class='PIA-flag' style='display:none; visibility:hidden;' title='This page is subject to the extended confirmed restriction related to the Arab-Israeli conflict.'></p>"
		end
	end
	
	return table.concat(ret)	
end

function p.main(frame, cfg)
	cfg = cfg or require(CONFIG_MODULE)

	-- Find default args, if any.
	local parent = frame.getParent and frame:getParent()
	local defaultArgs = parent and cfg.wrappers[parent:getTitle():gsub('/sandbox$', '')]

	-- Find user args, and use the parent frame if we are being called from a
	-- wrapper template.
	getArgs = getArgs or require('Module:Arguments').getArgs
	local userArgs = getArgs(frame, {
		parentOnly = defaultArgs,
		frameOnly = not defaultArgs
	})

	-- Build the args table. User-specified args overwrite default args.
	local args = {}
	for k, v in pairs(defaultArgs or {}) do
		args[k] = v
	end
	for k, v in pairs(userArgs) do
		args[k] = v
	end
	return p._main(args, cfg)
end

return p
印堂发黑是什么原因 惊恐发作是什么病 双子座后面是什么星座 儿童鼻炎挂什么科 梅菜是什么菜晒干的
双龙戏珠是什么生肖 1981属什么 纸上谈兵是什么生肖 金牛座是什么性格 严重脱发是什么病先兆
梦见洗头是什么预兆 石灰是什么 江西景德镇有什么好玩的地方 三查八对的内容是什么 洗衣机什么牌子最好
维生素b族为什么不能晚上吃 木瓜什么味道 珍珠翡翠白玉汤是什么 mm是什么意思单位 k14是什么金
什么叫形而上学hcv7jop7ns4r.cn 男人高冷是什么意思啊hcv7jop9ns7r.cn 右下眼皮跳是什么预兆hcv7jop9ns1r.cn 马来西亚有什么特产hcv7jop9ns7r.cn 上传下达什么意思bjhyzcsm.com
b型血为什么招蚊子xinjiangjialails.com 栅栏是什么意思hcv7jop9ns7r.cn 心悸什么意思hcv9jop3ns5r.cn 小雪时节吃什么hcv9jop7ns5r.cn 梦见放鞭炮是什么意思xinjiangjialails.com
医院附近适合做什么生意hcv9jop5ns8r.cn 肺实性结节是什么意思hcv7jop5ns5r.cn 调理是什么意思hcv8jop9ns2r.cn 小孩咳嗽挂什么科hcv9jop2ns9r.cn 什么是数位板hcv7jop9ns2r.cn
儿童扁桃体发炎吃什么药mmeoe.com 脊膜瘤是什么样的病hcv8jop9ns3r.cn 脸上起疙瘩是什么原因hcv9jop3ns6r.cn 胰腺炎为什么不能同房hcv9jop7ns4r.cn 风湿三项检查是什么hcv8jop5ns6r.cn
百度