Mô đun:Attached KML

-- Note: Originally written on English Wikipedia as w:en:Module:Attached_KML
-- ##### Localisation (L10n) settings #####
local L10n = {}
-- Template parameter names
-- (replace values in quotes with local parameter names)
L10n.para = {
	display		= "display",
	from		= "from",
	header		= "header",
	title		= "title",
	wikidata	= "wikidata",
	demo		= "demo",
}
-- Other configuration settings
L10n.config = {
	inline_format	= "box",			-- controls the format used for inline display, can be set to "box" (default) or "line"
							   -- "box" example: https://en.wikipedia.org/wiki/Template:Attached_KML
							   -- "line" example: https://sv.wikipedia.org/wiki/Mall:KML
}
-- Other strings
L10n.str = {
	inline		= "inline",			-- used with display parameter: (|display=inline) or (|display=title) or (|display=inline,title) or (|display=title,inline)
	title		= "title",			-- (as above)
	dsep		= ",",				-- separator between inline and title (comma in the example above)
	kml_prefix	= "Bản mẫu:Attached KML/",	-- local KML files are stored as subpages of this location
	default_title	= "Bản đồ lộ trình",			-- default title for links at top of page, when title parameter not used in transclusion
	default_header	= "",				-- default header for links in inline box, when header parameter not used in transclusion
	kml_file	= "Tập tin KML",			-- text to display for link to raw KML file
	edit		= "sửa",			-- text to display for link to edit KML file
	help		= "trợ giúp",			-- text to display for help page link
	help_location	= "Trợ giúp:Attached KML",		-- page to link to for help page link
	err_prepend	= "Attached KML",		-- text to prepend to the error messages, when shown at top of page (display=title)
	err		= {				-- error messages
		malformed_qid	= "Lỗi: mục id bị hỏng trong ",	-- item id doesn't match pattern (number with Q prefix)
		bad_qid		= "Lỗi: mục được định rõ trên Wikidata, hoặc trong , là không phải một tập tin KML (không tìm thấy P31→Q26267864)",	-- item doesn't have a P31→Q26267864 statement
		no_item		= "Lỗi: mục được định rõ trong  không tìm thấy trên Wikidata",	-- item not found on wikidata
		bad_from	= "Lỗi: Không tìm thấy tập tin KML, kiểm tra ",	-- KML specified by from parameter doesn't exist
		no_kml		= "Lỗi: Không tìm thấy tập tin KML",	-- no KML file found
	},
	cat		= {				-- tracking categories: full wikimarkup required, or set to the empty string ("") to not to track the condition
		wikidata_kml	= "Thể loại:Bài viết sử dụng KML từ Wikidata",	-- tracks mainspace articles using KML from Wikidata
		local_kml	= "Thể loại:Bài viết sử dụng KML không phải từ Wikidata",	-- tracks mainspace articles not using KML from Wikidata
		error_mqid	= "M",			-- tracks malformed_qid error
		error_badqid	= "W",			-- tracks bad_qid error
		error_noitem	= "N",			-- tracks no_item error
		error_from	= "F",			-- tracks bad_from error
		error_nokml	= "K",			-- tracks no_kml error
	},
	line		= {				-- these strings are only needed if using 'inline_format = "line"' configuration
		start		= "",				-- wikitext to display at start of line, may include image markup, should start with a space
		separator	= "",				-- text to display between links to external mapping providers, should include spaces
		},
}
-- Masks for external mapping providers, in the form:
--   externalLinkMasksindex-number = { short = "short-label", long = "long-label", link = "url" }'
-- The short label is used for the title links; the long label is used for the inline links
-- Links in the output will be ordered by index-number
-- Instead of kml file's raw url or encoded raw url, use  __KML_URL__  or  __KML_URL_E__
local externalLinks = {}
--externalLinks1 = { 
--	short = "Bing",
--	long  = "Hiển thị trên Bing Maps",
--	link  = "http://www.bing.com/maps/?mapurl=__KML_URL__"
--}
-- #### End of L10n settings ####
-- Table of available wikis, in the order that they are to be searched for kml files
-- (once a kml file is found, further sites are not checked)
local sites = {}
sites1  = { mw.ustring.match( mw.site.server, "%w+" )  ..  mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "mpedia", ""),  mw.ustring.sub(mw.site.server, 3), "" } -- local wiki (listed first so local files can override files on other wikis)
sites2  = { "commonswiki", "commons.wikimedia.org", "c:" } -- Commons would be a logical central repository for KML files (but has no files as of August 2016)
sites3  = { "enwiki", "en.wikipedia.org", "w:en:" } -- largest source of KML files (as of August 2016)
sites4  = { "bnwiki", "bn.wikipedia.org", "w:bn:" } -- other sites with a KML template, listed in alphabetical order
sites5  = { "cswiki", "cs.wikipedia.org", "w:cs:" } 
sites6  = { "fawiki", "fa.wikipedia.org", "w:fa:" } 
sites7  = { "frwiki", "fr.wikipedia.org", "w:fr:" } 
sites8  = { "jawiki", "ja.wikipedia.org", "w:ja:" } 
sites9  = { "mlwiki", "ml.wikipedia.org", "w:ml:" } 
sites10 = { "svwiki", "sv.wikipedia.org", "w:sv:" } 
sites11 = { "zhwiki", "zh.wikipedia.org", "w:zh:" } 
--Parameter for cleaned-up parent.args (whitespace trimmed, blanks removed)
local Args = {}
local p = {}
function p.main(frame)
	local parent = frame.getParent(frame)
	Args = setCleanArgs(parent.args)
	local qid = ArgsL10n.para.wikidata or nil
	-- get KML file url
	local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError
	if not (ArgsL10n.para.from) then
		if not qid then
			wikiUrl, wikiLink, siteindex, kmlError = getUrlFromWikidata()
		elseif  mw.ustring.find( qid, "^Q%d+" ) then
			wikiUrl, wikiLink, siteindex, kmlError = getUrlFromQid(qid)
		else
			kmlError = makeError(L10n.str.err.malformed_qid, L10n.str.cat.error_mqid)
		end
	end
	if not (wikiUrl) then
		wikiLink = ArgsL10n.para.from or mw.title.new(tostring(mw.title.getCurrentTitle())).text
		wikiLink = L10n.str.kml_prefix .. wikiLink
		wikiTitle = mw.title.new( wikiLink )
		if not (wikiTitle.exists) and not (kmlError) then
			if ArgsL10n.para.from then
				kmlError = makeError(L10n.str.err.bad_from, L10n.str.cat.error_from)
			else
				kmlError = makeError(L10n.str.err.no_kml, L10n.str.cat.error_nokml)
			end
		end
		wikiUrl = wikiTitle:fullUrl("action=raw","https")
		siteindex = 1
		trackingWikitext =  mw.ustring.format( "KML không phải từ Wikidata", L10n.str.cat.local_kml )
	else
		trackingWikitext =  mw.ustring.format( "KML từ Wikidata", L10n.str.cat.wikidata_kml )
	end
	-- replace __KML_URL__ or __KML_URL_E__ with actual values
	local encodedWikiUrl = mw.uri.encode(wikiUrl, "PATH")
	for i, v in ipairs( externalLinks ) do
		local el1 = safeReplace( v.link, "__KML_URL__", wikiUrl )
		local el2 = safeReplace( el1, "__KML_URL_E__", encodedWikiUrl )
		externalLinksi"link" = el2
	end
	-- suppress errors and categories if demo parameter is set
	if ArgsL10n.para.demo then
		kmlError = nil
		trackingWikitext = ""
	end
	local wikitext = ""
	if ArgsL10n.para.display then
		local display = mw.text.split(ArgsL10n.para.display, '%s*' .. L10n.str.dsep .. '%s*')
		if display1 == L10n.str.title or display2 == L10n.str.title then
			wikitext = makeTitleWikitext(ArgsL10n.para.title or L10n.str.default_title, kmlError)
		end
		if display1 == L10n.str.inline or display2 == L10n.str.inline or (display1 ~= L10n.str.title and display2 ~= L10n.str.title) then
			local inlineWikitext = makeInlineWikitext(ArgsL10n.para.header or L10n.str.default_header, wikiUrl, kmlError)
			wikitext = wikitext .. inlineWikitext
		end
	else
		wikitext = makeInlineWikitext(ArgsL10n.para.header or L10n.str.default_header, wikiUrl, kmlError)
	end
	wikitext = wikitext .. makeKmldataDiv(wikiLink, siteindex) .. trackingWikitext
	return frame:preprocess( wikitext )
end
function setCleanArgs(argsTable)
	local cleanArgs = {}
	for key, val in pairs(argsTable) do
		if type(val) == 'string' then
			val = val:match('^%s*(.-)%s*$')
			if val ~=  then
				cleanArgskey = val
			end
		else
			cleanArgskey = val
		end
	end
	return cleanArgs
end
function safeReplace(string, pattern, replacement)
	-- avoids "Lua error: invalid capture index" that occurs with string.gsub when the replacement contains one or more literal % character
	local nonpattern_parts = mw.text.split( string, pattern )
	return table.concat(nonpattern_parts, replacement)
end
function makeTitleWikitext(titletext, err)
	if err and L10n.str.err_prepend then err =  mw.ustring.gsub( err, ">", ">" .. L10n.str.err_prepend .. " ", 1 ) end
	local titleLinks = {}
	for i, v in ipairs( externalLinks ) do
		titleLinksi =  mw.ustring.format( "%s %s", v.link , v.short)
	end
	return  mw.ustring.format( "\'\'\'%s\'\'\': %s", titletext, err or table.concat(titleLinks, " / ") ) 
end
function makeInlineWikitext(headertext, url, err)
	local inlineLinks = {}
	for i, v in ipairs( externalLinks ) do
		inlineLinksi =  mw.ustring.format( "%s %s", v.link , v.long)
	end
	local editUrl =  mw.ustring.gsub( url, "action=raw", "action=edit" )
	local wiki_link_class
	if  mw.ustring.find( editUrl, mw.site.server, 1, true ) then
		wiki_link_class = "plainlinks"
	else
		wiki_link_class = ""
	end
	if L10n.config.inline_format == "line" then
		return  mw.ustring.format( "%s%s%s (%s %s (%s %s • %s))", headertext, L10n.str.line.start, err or table.concat(inlineLinks, L10n.str.line.separator), wiki_link_class, url, L10n.str.kml_file, editUrl, L10n.str.edit, L10n.str.help_location, L10n.str.help)
	else
		return  mw.ustring.format( "%s\'\'\'%s %s\'\'\' (%s %s • %s)\n%s", headertext, wiki_link_class, url, L10n.str.kml_file, editUrl, L10n.str.edit, L10n.str.help_location, L10n.str.help, err or table.concat(inlineLinks, "") )
	end
end
function makeKmldataDiv(link, s_index)
	return  mw.ustring.format( "%s%s", sitess_index2, link, sitess_index3, link )
end
function makeError(msg, cat)
	return  mw.ustring.format( "%s%s%s%s%s%s", "",  mw.ustring.gsub( msg, "", "" ), "", "")
end
function getUrlFromWikidata()					-- Attempts to get url from linked wikidata items, will return nil if it can't
	local entity = mw.wikibase.getEntityObject()
	if not entity then return nil end			
	local kml_claim = entity:getBestStatements("P3096")	-- P3096 is property "KML file"
	
	if kml_claim then
		-- get the QID of the first value of the property
		if (kml_claim1 and kml_claim1.mainsnak.snaktype == "value" and kml_claim1.mainsnak.datavalue.type == "wikibase-entityid") then
			local kml_qid = "Q" .. kml_claim1.mainsnak.datavalue.value"numeric-id"
			return getUrlFromQid( kml_qid )
		else
			return nil	-- TODO: error message
		end
	else
		return nil	-- TODO: error message
	end
end
function getUrlFromQid( kml_qid )
	local pcall_result, kml_entity = pcall(mw.wikibase.getEntity, kml_qid)
	if not pcall_result then return nil, nil, nil, makeError(L10n.str.err.no_item, L10n.str.cat.error_noitem) end -- Error if entity doesn't exist
	local p31_claim = kml_entity:getBestStatements("P31")		-- P31 is property "instance of"
	local has_good_p31
	for k, v in pairs( p31_claim ) do
		if (p31_claimk and p31_claimk.mainsnak.snaktype == "value" and p31_claimk.mainsnak.datavalue.type == "wikibase-entityid" and p31_claimk.mainsnak.datavalue.value"numeric-id" == 26267864) then
			has_good_p31 = true
		end
	end
	if not (has_good_p31) then return nil, nil, nil, makeError(L10n.str.err.bad_qid, L10n.str.cat.error_badqid) end -- Error if item isn't a kml file
	local kml_sitelink
	local kml_siteindex
	local kml_url
	for i, v in ipairs( sites ) do
		kml_sitelink = kml_entity:getSitelink( v1 )
		if kml_sitelink then
			kml_url = "https://" .. v2 .. "/w/index.php?title=" .. mw.uri.encode( kml_sitelink, "WIKI" ) .. "&action=raw"
			kml_siteindex = i
		end
		if kml_url then break end
	end
	return kml_url or nil, kml_sitelink or nil, kml_siteindex or nil, nil
end
return p