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 |" .. L10n.para.wikidata .. "=", -- 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 |" .. L10n.para.wikidata .. "=, 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 |" .. L10n.para.wikidata .. "= 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 |" .. L10n.para.from .. "=", -- 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 = "", -- tracks mainspace articles using KML from Wikidata
local_kml = "", -- tracks mainspace articles not using KML from Wikidata
error_mqid = "", -- tracks malformed_qid error
error_badqid = "", -- tracks bad_qid error
error_noitem = "", -- tracks no_item error
error_from = "", -- tracks bad_from error
error_nokml = "", -- 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:
-- externalLinkMasks[index-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 = {}
--externalLinks[1] = {
-- 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 = {}
sites[1] = { mw.ustring.match( mw.site.server, "%w+" ) .. mw.ustring.gsub( mw.ustring.lower(mw.site.siteName), "[mp]edia", ""), mw.ustring.sub(mw.site.server, 3), "" } -- local wiki (listed first so local files can override files on other wikis)
sites[2] = { "commonswiki", "commons.wikimedia.org", "c:" } -- Commons would be a logical central repository for KML files (but has no files as of August 2016)
sites[3] = { "enwiki", "en.wikipedia.org", "w:en:" } -- largest source of KML files (as of August 2016)
sites[4] = { "bnwiki", "bn.wikipedia.org", "w:bn:" } -- other sites with a KML template, listed in alphabetical order
sites[5] = { "cswiki", "cs.wikipedia.org", "w:cs:" }
sites[6] = { "fawiki", "fa.wikipedia.org", "w:fa:" }
sites[7] = { "frwiki", "fr.wikipedia.org", "w:fr:" }
sites[8] = { "jawiki", "ja.wikipedia.org", "w:ja:" }
sites[9] = { "mlwiki", "ml.wikipedia.org", "w:ml:" }
sites[10] = { "svwiki", "sv.wikipedia.org", "w:sv:" }
sites[11] = { "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 = Args[L10n.para.wikidata] or nil

-- get KML file url
local wikiUrl, wikiTitle, wikiLink, trackingWikitext, kmlError
if not (Args[L10n.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 = Args[L10n.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 Args[L10n.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||%s}}", L10n.str.cat.local_kml )
else
trackingWikitext = mw.ustring.format( "KML từ Wikidata||%s}}", 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 )
externalLinks[i]["link"] = el2
end

-- suppress errors and categories if demo parameter is set
if Args[L10n.para.demo] then
kmlError = nil
trackingWikitext = ""
end

local wikitext = ""
if Args[L10n.para.display] then
local display = mw.text.split(Args[L10n.para.display], '%s' .. L10n.str.dsep .. '%s')
if display[1] L10n.str.title or display[2] L10n.str.title then
wikitext = makeTitleWikitext(Args[L10n.para.title] or L10n.str.default_title, kmlError)
end
if display[1] L10n.str.inline or display[2] L10n.str.inline or (display[1] ~= L10n.str.title and display[2] ~= L10n.str.title) then
local inlineWikitext = makeInlineWikitext(Args[L10n.para.header] or L10n.str.default_header, wikiUrl, kmlError)
wikitext = wikitext .. inlineWikitext
end
else
wikitext = makeInlineWikitext(Args[L10n.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
cleanArgs[key] = val
end
else
cleanArgs[key] = 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
titleLinks[i] = 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
inlineLinks[i] = 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", sites[s_index][2], link, sites[s_index][3], link )

end

function makeError(msg, cat)
return mw.ustring.format( "%s%s%s%s%s%s", "", mw.ustring.gsub( msg, "", "" ), "", "||=", cat, "}}")
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_claim[1] and kml_claim[1].mainsnak.snaktype "value" and kml_claim[1].mainsnak.datavalue.type "wikibase-entityid") then
local kml_qid = "Q" .. kml_claim[1].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_claim[k] and p31_claim[k].mainsnak.snaktype "value" and p31_claim[k].mainsnak.datavalue.type "wikibase-entityid" and p31_claim[k].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( v[1] )
if kml_sitelink then
kml_url = "https://" .. v[2] .. "/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