跳转到内容

模組:Lockbox/sandbox

维基百科,自由的百科全书
local export = {}

local function generate_transclusion(title)
	if type(title) == 'string' then
		title = mw.title.new(title)
	end
	-- T373047 MediaWiki 1.43+ 新增了欄位 title.content,此前的版本應該使用 title:getContent()
	return title.content
end

local function make_wikitext_warning(msg)
	return string.format('<strong class="warning">Warning: %s.</strong>', msg)
end

local function in_array(arr, item)
	for _, v in ipairs(arr) do
		if v == item then
			return true
		end
	end
	return false
end

local function get_module_title()
	-- 獲取模組的標題
	-- 如果被引用(有 frame.getParent())則生成一個新的 mw.title
	-- 否則返回 mw.title.getCurrentTitle()(因為此時 frame:getTitle() == mw.title.getCurrentTitle().prefixedText)
	local frame = mw.getCurrentFrame()
	if frame:getParent() then
		return mw.title.new(frame:getTitle())
	end
	return mw.title.getCurrentTitle()
end

local function title_is_cascading_protection(title, override_module_title)
	-- @param title {mw.title}
	-- @param override_module_title {mw.title} 僅供 debug 使用

	-- 第一種方法:檢查自己的連鎖保護來源是不是空的
	if #title.cascadingProtection.sources > 0 then
		return true
	end
	
	local module_title = override_module_title or get_module_title()
	if module_title and module_title ~= title then
		-- 第二種方法:檢查自己是否在模組的連鎖保護來源裡
		if in_array(module_title.cascadingProtection.sources, title.prefixedText) then
			return true
		end
	end

	return false
end

-- DEBUG
-- export._title_is_cascading_protection = title_is_cascading_protection

function export.lock(frame)
	local warnings, transclusion_list = {}, {}

	-- 確認頁面是否是連鎖保護
	-- 曾經這是通過自我引用後檢查自己有沒有被連鎖保護(見下方註釋)
	-- 不過那種方式貌似失效了
	-- 參數 skipCascadingCheck 會直接跳過這個檢查
	if not args.skipCascadingCheck and not title_is_cascading_protection(mw.title.getCurrentTitle()) then
		warnings[#warnings + 1] = make_wikitext_warning(string.format(
			'the page "%s" is not cascade-protected',
			parent_title
		))
	end
	--
	-- Only pages transcluded from a cascade-protected page appear in
	-- CASCADINGSOURCES, so normally we would not be able to tell if the lockbox
	-- itself is cascade-protected. To work around this, we generate a
	-- transclusion from the lockbox to itself, so that it will have an entry
	-- for itself in CASCADINGSOURCES.
	--
	-- We cannot generate this transclusion using the title object for the
	-- parent title (the lockbox), as if the lockbox is transcluded on another
	-- page, we will generate a transclusion *from* the lockbox *to* that page
	-- as well, and the page will be cascade-protected. Instead we generate it
	-- with the title object for the current title.
	--
	-- When the current title is the parent title (i.e. we are rendering the
	-- lockbox page), this creates the required entry in the link table in the
	-- database. When the current title is the grandparent title or up (i.e. we
	-- are rendering a page transcluding the lockbox), transclusions are only
	-- created from the page itself, not from the lockbox, and it is not
	-- cascade-protected.
	-- 
	-- This creates an extaneous self-transclusion for all pages using the
	-- module, but we treat that as a necessary evil.
	--
	-- XXX: there seems to be no way to check for cascading protection using a
	-- Scribunto API, so we have to use frame:preprocess with the
	-- CASCADINGSOURCES parser function.
	-- 註:title.cascadingProtection 於 2014-08 mediawiki-extensions-Scribunto #fd9ecb9 引入
	-- do
	-- 	mw.title.getCurrentTitle():getContent() -- Generate self-transclusion
	-- 	local parent_title = frame:getParent():getTitle()
	-- 	if frame:preprocess('{{CASCADINGSOURCES:' .. parent_title .. '}}') == '' then
	-- 		warnings[#warnings + 1] = make_wikitext_warning(string.format(
	-- 			'the page "%s" is not cascade-protected',
	-- 			parent_title
	-- 		))
	-- 	end
	-- end

	-- Generate transclusions to the templates, and build the output list.
	for i, item in ipairs(frame.args) do
		item = mw.text.trim(item)
		local title = mw.title.new(item)
		if title then
			local ns = title.namespace
			local prefixed_text = title.prefixedText
			if ns == 0 then
				-- The item had no namespace text. If the item starts with a
				-- colon, assume it is a mainspace page. Otherwise, assume it is
				-- a template.
				if item:sub(1, 1) == ':' then
					generate_transclusion(title)
					table.insert(transclusion_list, '* [[' .. prefixed_text .. ']]')
				else
					generate_transclusion('Template:' .. prefixed_text)
					table.insert(transclusion_list, '* [[Template:' .. prefixed_text .. ']]')
				end
			elseif ns == 6 or ns == 14 then -- File or Category namespace
				generate_transclusion(title)
				table.insert(transclusion_list, '* [[:' .. prefixed_text .. ']]')
			else
				generate_transclusion(title)
				table.insert(transclusion_list, '* [[' .. prefixed_text .. ']]')
			end
		else
			warnings[#warnings + 1] = make_wikitext_warning(string.format(
				'invalid title "%s" in argument #%d',
				item,
				i
			))
		end
	end

	if frame.args.silent then
		return ''
	else
		-- If there were any warnings, show them at the top. Then show the list
		-- of transcluded pages.
		local ret = ''
		if #warnings > 0 then
			if #warnings > 1 then
				for i, warning in ipairs(warnings) do
					warnings[i] = '* ' .. warning
				end
			end
			ret = ret .. table.concat(warnings, '\n') .. '\n\n'
		end
		return ret .. table.concat(transclusion_list, '\n')
	end
end

return export