Jump to content

Module:Attached KML

Permanently protected module
From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by Evad37 (talk | contribs) at 23:39, 23 August 2016 (expand sidebox template). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

-- ##### 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",
}

-- 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 in the above)
	kml_prefix     = "Template:Attached KML/",	-- local KML files are stored as subpages of this location
	default_title  = "Route map",			-- 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
}

-- Masks for external mapping providers, in the form:
--   externalLinkMasks[index-number] = { short = "short-label", long = "long-label", link = "url" }'
-- 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  = "Display on Bing Maps",
	link  = "http://www.bing.com/maps/?mapurl=__KML_URL__"
}
externalLinks[2] = {
	short = "Google",
	long  = "Display on Google Maps",
	link  = "https://tools.wmflabs.org/wp-world/googlmaps-proxy.php?page=__KML_URL_E__&output=classic"
}

-- #### 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.log( string.match( mw.site.server, "%w." )  .. string.gsub(string.lower(mw.site.siteName), "[mp]edia", "") ), string.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:sr:" } 
sites[11] = { "zhwiki", "zh.wikipedia.org", "w:zh:" } 


local p = {}

function p.main(frame)
	local parent = frame.getParent(frame)
	local qid = parent.args[L10n.para.wikidata] or nil

	-- get KML file url
	local wikiUrl, wikiLink, trackingWikitext
	if not (parent.args[L10n.para.from]) then
		if not qid then
			wikiUrl, wikiLink, siteindex = getUrlFromWikidata()
		elseif string.find( qid, "^Q%d+" ) then
			wikiUrl, wikiLink, siteindex = getUrlFromQid(qid)
		else
			-- TODO: report error
		end
	end
	if not (wikiUrl) then
		wikiLink = parent.args[L10n.para.from] or tostring(mw.title.getCurrentTitle())
		wikiUrl = mw.title.new( L10n.str.kml_prefix .. wikiLink ):fullUrl("action=raw","https")
		siteindex = 1
		trackingWikitext = "<div title=\"KML & Wikidata\" style=\"display:none;\">KML is not from Wikidata</div>{{main other|[[Category:Articles using KML not on Wikidata]]}}"
	else
		trackingWikitext = "<div title=\"KML & Wikidata\" style=\"display:none;\">KML is from Wikidata</div>{{main other|[[Category:Articles using KML from Wikidata]]}}"
	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

	local wikitext = ""
	if parent.args[L10n.para.display] then
		local display = mw.text.split(parent.args[L10n.para.display], L10n.str.dsep)
		if display[1] == L10n.str.title or display[2] == L10n.str.title then
			wikitext = makeTitleWikitext(parent.args[L10n.para.title] or L10n.str.default_title)
		end
		if display[1] == "inline" or display[2] == "inline" then
			local inlineWikitext = makeInlineWikitext(parent.args[L10n.para.header] or L10n.str.default_header, wikiUrl)
			wikitext = wikitext .. inlineWikitext
		end
	else
		wikitext = makeInlineWikitext(parent.args[L10n.para.header] or L10n.str.default_header, wikiUrl)
	end
	wikitext = wikitext .. makeKmldataDiv(wikiLink, siteindex) .. trackingWikitext

	return frame:preprocess( wikitext )

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)
	local titleLinks = {}
	for i, v in ipairs( externalLinks ) do
		titleLinks[i] = string.format( "[%s %s]", v.link , v.short)
	end
	return string.format( "<span style=\"font-size: small;\"><span id=\"coordinates\">\'\'\'%s\'\'\': %s</span></span>", titletext, table.concat(titleLinks, " / ") ) 
end


function makeInlineWikitext(headertext, url)
	local inlineLinks = {}
	for i, v in ipairs( externalLinks ) do
		inlineLinks[i] = string.format( "[%s %s]", v.link , v.long)
	end
	local editUrl = string.gsub( url, "action=raw", "action=edit" )
	local wiki_link_class
	if string.find( editUrl, mw.site.server, 1, true ) then
		wiki_link_class = "plainlinks"
	else
		wiki_link_class = ""
	end

	return string.format( "<table class=\"metadata mbox-small\" style=\"border:1px solid #aaa;background-color:#f9f9f9;font-size: 88%%; line-height: 1.5em\"><tr><td style=\"width:1px\"></td><td class=\"mbox-text plainlist\">%s<span class=\"%s\">\'\'\'[%s KML file]\'\'\' ([%s edit] • [[Help:Attached KML|help]])</span>\n<ul><li>%s</li></ul></td></tr></table>", headertext, wiki_link_class, url, editUrl, table.concat(inlineLinks, "</li><li>") )
end

function makeKmldataDiv(link, s_index)
	return string.format( "<div class=\"kmldata\" data-server=\"%s\" title=\"%s\" style=\"display:none;\">[[%s%s]]</div>", sites[s_index][2], link, sites[s_index][3], link )

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
		end
	else
		return nil
	end
end


function getUrlFromQid( kml_qid )
	local kml_entity = mw.wikibase.getEntity( kml_qid )
	if not kml_entity then return nil end
	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
end

return p