Jump to content

Module:Infobox mapframe

From GaplaWiki
Revision as of 18:55, 9 May 2026 by Wsbaek (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Infobox mapframe/doc

local mf = require('Module:Mapframe')
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local infoboxImage = require('Module:InfoboxImage').InfoboxImage

-- Wikibase safety layer
local wikibase = mw.wikibase
local function hasWikibase()
	return wikibase ~= nil
end

-- Defaults
local DEFAULT_FRAME_WIDTH = "270"
local DEFAULT_FRAME_HEIGHT = "200"
local DEFAULT_ZOOM = 10

local util = {}

function util.noop()
	return ""
end

function util.trimArgs(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

-- SAFE Wikidata access
function util.getBestStatement(item_id, property_id)
	if not hasWikibase() then return false end
	if not item_id then return false end
	if not wikibase.isValidEntityId(item_id) then return false end
	if not wikibase.entityExists(item_id) then return false end

	local statements = wikibase.getBestStatements(item_id, property_id)
	if not statements or #statements == 0 then return false end

	local snak = statements[1].mainsnak
	if snak and snak.snaktype == 'novalue' then return false end

	return statements[1]
end

function util.getStatementValue(statement)
	return statement and statement.mainsnak
		and statement.mainsnak.datavalue
		and statement.mainsnak.datavalue.value
end

function util.relatedEntity(item_id, property_id)
	local val = util.getStatementValue(util.getBestStatement(item_id, property_id))
	return val and val.id or nil
end

function util.shouldAutoRun(frame)
	local pargs = frame:getParent().args
	local explicitlyOn = yesno(mw.text.trim(pargs.mapframe or ""))
	local onByDefault = (explicitlyOn == nil) and yesno(frame.args.onByDefault or "", false)
	return explicitlyOn or onByDefault
end

function util.argsFromAuto(frame)
	local args = getArgs(frame, { parentFirst = true })
	local fixed = {}

	for k, v in pairs(args) do
		local name = k:match("^mapframe%-(.+)$")
		if name then
			fixed[name] = v
		elseif (k == "coord" or k == "coordinates") and not fixed.coord then
			fixed.coord = v
		elseif (k == "id" or k == "qid") and not fixed.id then
			fixed.id = v
		end
	end
	return fixed
end

-- Caption
local function getLabel(id)
	return hasWikibase() and id and wikibase.getLabel(id)
end

local p = {}

p._caption = function(args)
	if args.caption then return args.caption end
	local label = getLabel(args.id)
	return label and ("Location of " .. label) or ""
end

p._main = function(config)
	config = util.trimArgs(config)

	local args = {}
	args.frame = "yes"
	args.plain = "yes"
	args["frame-width"] = config.width or DEFAULT_FRAME_WIDTH
	args["frame-height"] = config.height or DEFAULT_FRAME_HEIGHT

	local coord = config.coord or config.coordinates
	local id = config.id or (hasWikibase() and wikibase.getEntityIdForCurrentPage())

	if not coord and not id then
		return false, ""
	end

	args.zoom = config.zoom or DEFAULT_ZOOM

	-- Point marker only (safe fallback)
	if coord then
		args.type = "point"
		args.coord = coord
	end

	local map = mf._main(args)
	return true, map
end

p.autoWithCaption = function(frame)
	if not util.shouldAutoRun(frame) then return "" end

	local args = util.argsFromAuto(frame)

	local ok, map = p._main(args)
	if not ok then return map end

	map = frame:preprocess(map)
	local caption = p._caption(args)

	local html = mw.html.create()
	html:wikitext(map)
	html:tag("div")
		:addClass("infobox-caption")
		:wikitext(caption)

	return tostring(html)
end

return p