local p = {}
local yesno = require("Module:Yesno")
local func_removeNoinclude = {}
function p.templateExist(input_data, _depth, _max_depth, _recursion_list, _removeNoinclude)
--===讀取Lua調用之參數 和 提供預設值===
local template_name = input_data --待判斷模板名稱
local count = 1 --幾個該模板視為存在 (預設為有1個就視為存在)
local return_count = false --返回值是否為模板數量,"是" 返回模板數量、"否" 返回存在與否
local depth = _depth or 0 --目前搜索深度,預設為0
local max_depth = _max_depth or 1 --最大搜索深度,預設為一層
local recursion_list = {} --已造訪過的模板
for key, value in pairs(_recursion_list or {}) do recursion_list[key] = value end --寫入先前已造訪過的模板
local removeNoinclude = _removeNoinclude or (function(_str)return _str end) --內文前處理函數
local currentTitle = mw.title.getCurrentTitle() --要找模板的頁面,預設為所在頁面
--===讀取模板調用之參數===
if type(input_data) == type({}) and type(input_data.args) == type({}) then
--參數 |1= 模板名稱
template_name = input_data.args[1] or input_data.args['1'] or ''
--參數 |count= 多少數量視為存在;或是否返回數量
local _count = tonumber(input_data.args.count)
if type(_count) == type(nil) then --count參數不是數字時
--檢查count參數是不是布林值
return_count = yesno(tostring(input_data.args.count))
end
count = _count or count --多少數量模板視為存在
--參數 |depth= 最大搜尋深度
max_depth = tonumber(input_data.args.depth) or max_depth
--參數 |page= 要尋找模板的頁面。未輸入使用本調用所在頁面
local page = input_data.args.page --是否檢查特定頁面
if mw.text.trim(page or '') ~= '' then --有輸入頁面名稱
--檢查頁面名稱是否合法
local success, page_obj = pcall(mw.title.new, page)
if success and type((page_obj or {}).getContent) == type(tostring) then
--頁面名稱是否合法的話,就檢查參數 |page= 提供的頁面
currentTitle = page_obj
end
end
end
local function _return(_value) -- 返回值模式
return return_count
and _value --如果是模板計數,返回指定模板數量
or (_value >= count) --否則返回模板存在與否
end
--===開始判斷模板是否存在===
--取得判斷目標的模板
local template_title = p.getTemplateTitle(template_name)
--模板計數 (還沒開始找模板,所以是0)
local template_count = 0
if --如果模板和待判斷頁面都合法
type((template_title or {}).getContent) == type(tostring) and
type((currentTitle or {}).getContent) == type(tostring)
then --開始尋找模板
--如發現模板循環,直接退出
if mw.title.equals(template_title, currentTitle) then return _return(0) end
if recursion_list[tostring(currentTitle)] then return _return(0) end
recursion_list[tostring(currentTitle)] = true
--取得待判斷頁面內容
local content = removeNoinclude(currentTitle:getContent() or '')
--檢查待判斷頁面中所有格式為 {{XXX 的內容
for capture in mw.ustring.gmatch('-'..content, "[^%{]%{%{%s*([^%{%}%|]+)%s*[%}%|]") do
--解析出 {{XXX 的模板名稱
local check_template_name = mw.text.trim(capture or '')
local check_module = mw.ustring.match(check_template_name, "%s*#%s*[Ii][Nn][Vv][Oo][Kk][Ee]%s*:%s*([^%{%}%|]+)%s*$")
if check_module then check_template_name = "Module:"..check_module end
--取得該模板名稱對應的模板物件
local check_template_title = p.getTemplateTitle(check_template_name)
if check_template_title then --模板物件存在
--看看該模板跟待判斷的模板是否為同一個
if mw.title.equals(check_template_title, template_title) then
--如果是,模板計數遞增
template_count = template_count + 1
elseif depth + 1 < max_depth then --是否深度搜索
func_removeNoinclude = (type(func_removeNoinclude) == type(tostring)) and func_removeNoinclude or require("Module:Special_wikitext/Custom_Module/tools").removeNoinclude
template_count = template_count --看看待判斷的模板是否在其他模板裡面
+ p.templateExist( --進入模板判斷
{args={
tostring(template_title), --要判斷的模板保持不變
count=true, --計數模式
page=tostring(check_template_title) --進入模板
}},
depth + 1, max_depth, recursion_list, --增加深度
func_removeNoinclude
)
--紀錄已進入過的模板,避免模板循環
recursion_list[tostring(check_template_title)] = true
end --模板跟待判斷的模板不是同一個,不做動作
end --判斷下一個模板
end --所有模板檢查完畢
end
return _return(template_count) --偵測完畢,返回結果
end
function p.getTemplateTitle(input_data)
local template_name = input_data
local is_lua = true
if type(input_data) == type({}) and type(input_data.args) == type({}) then
--讀取模板呼叫的參數
template_name = input_data.args[1] or input_data.args['1'] or ''
end
local function _return(_value) --區分模板呼叫或模組呼叫
if is_lua then return _value
else return _value and tostring(_value) or '' end
end
template_name = mw.text.trim(template_name or '')
--未輸入,返回空
if template_name == '' then return _return() end
--嘗試取得待偵測模板
local success, template_obj = pcall(mw.title.new, template_name, "Template")
--取得失敗返回空
if (not success) or type((template_obj or {}).getContent) ~= type(tostring) then return _return() end
--取得模板原名 (模板可能是重定向)
local page_name = tostring(template_obj)
local template_title = (template_obj or{}).redirectTarget or template_obj
local redircct_name = tostring(template_title)
--如果模板不能讀取內容 (它是假的模板) 返回空
if type((template_title or{}).getContent) ~= type(tostring)then return _return() end
--如果模板存在,返回模板物件
if type(template_title:getContent()) == type("string") then
return _return(template_title)
end
local lib_zhcvt = require('Module:ZhConversion') --繁簡轉換
for _, check_title in ipairs({ --列舉繁簡的可能
lib_zhcvt.to_hant(page_name), lib_zhcvt.to_hans(page_name),
lib_zhcvt.to_hant(redircct_name), lib_zhcvt.to_hans(redircct_name),
}) do --檢查各種繁簡模式
--嘗試取得該繁簡模式的模板
local _success, check_page = pcall(mw.title.new, check_title, "Template")
--如果是可讀取的模板
if _success and type(check_page.getContent) == type(tostring) then
--排除重新導向
check_page = check_page.redirectTarget or check_page
--模板存在,返回模板物件
if type(check_page:getContent()) == type("string") then
return _return(check_page)
end
end
end
--測試不通過,返回空
return _return()
end
return p