Modul:Administrative area

Fra Wikipedia, den frie encyklopedi
Moduldokumentasjon
-- Specialized helper module for navboxes for administrative areas
-- © John Erling Blad, Creative Commons by Attribution 3.0

-- don't pollute with globals
require('strict')

-- find the first entry that seems to be a non Q-id
-- @param table args argument list from the frame
-- @return string first non-matching argument
local function findNotQID( args )
	for key, value in ipairs( args ) do
		if value ~= '' and not string.match(value, '^Q%d+$') then
			return value
		end
	end
	return nil
end

-- find the first entry that seems to be a Q-id
-- @param table args argument list from the frame
-- @return string first matching argument
local function findQID( args )
	for key, value in ipairs( args ) do
		if value ~= '' and string.match(value, '^Q%d+$') then
			return value
		end
	end
	local entity = mw.wikibase.getEntity()
	if entity then
		return entity['id']
	end
	return nil
end

-- numeric IDs from statement
-- @param table statement well-defined structure for a statement
-- @return id or nil
local function findId(statement)
	local mainsnak = statement["mainsnak"]
	if mainsnak then
		local datavalue = mainsnak['datavalue']
		if datavalue then
			local value = datavalue['value']
			if value then
				return value['numeric-id'] or nil
			end
		end
	end
	return nil
end

-- numeric IDs from all statements
-- @param table statement well-defined structure for a statement
-- @return table with ids
local function findIds(statements)
	local ids = {}
	for _,statement in pairs(statements) do
		local id = findId(statement)
		if id then
			ids[1+#ids] = id
		end
	end
	return ids
end

-- value from statement
-- @param table statement well-defined structure for a statement
-- @return value or nil
local function findValue(statement)
	local mainsnak = statement["mainsnak"]
	if mainsnak then
		local datavalue = mainsnak['datavalue']
		if datavalue then
			return datavalue['value'] or nil
		end
	end
	return nil
end

-- values from all statements
-- @param table statement well-defined structure for a statement
-- @return table woth values
local function findValues(statements)
	local values = {}
	for _,statement in pairs(statements) do
		local value = findValue(statement)
		if value then
			values[1+#values] = value
		end
	end
	return values
end

-- load a list of statements and format the entries according to build directive
-- @param string id some entity to load
-- @param string prop id for the property to use
-- @param string back id for the inverse property (optional)
-- @return table
local function loadStatements( qid, prop, back )
	local entity = qid and mw.wikibase.getEntity( qid ) or mw.wikibase.getEntity()
	local statements = entity:getBestStatements( prop )
	if not statements then
		return {}
	end
	if back then
		local filtered = {}
		for _,statement in pairs(statements) do
			local found = 0
			local id = findId(statement)
			if id then
				for _,v in pairs( findIds( loadStatements( 'Q'..id, back ) ) ) do
					if qid == 'Q'..v then
						found = 1+found
					end
				end
			end
			if found >  0 then
				filtered[1+#filtered] = statement
			end
		end
		return filtered
	end
	return statements
end

-- @var table forward declaration of build methods
local Build

-- access function for the Build lookup table
-- @param string qid identifies the entity to process
-- @param string directive how to format the result (ie. the lookup key)
-- @return string wiki formatted string
local function build( qid, directive )
	if Build[directive] then
		return Build[directive]( qid )
	end
	return qid
end

-- format the entries according to build directive
-- @param table statements to be formatted according to the directive
-- @param string directive how to format the entries
-- @return string with a possible error entry as second return value
local function formatStatements( statements, directive )
	local entries = {}
	for _,id in ipairs( findIds( statements ) ) do
		entries[1+#entries] = build( 'Q' .. id, directive )
	end
	return table.concat( entries, ' · ' )
end

Build = {
	verbatim = function( qid )
		local label = mw.wikibase.label( qid ) or qid
		return label
	end,

	title = function( qid )
		local label = mw.wikibase.label( qid ) or qid
		return "'''" .. label .. "'''"
	end,

	link = function( qid )
		local sitelink = mw.wikibase.sitelink( qid )
		local label = mw.wikibase.label( qid ) or qid
		if sitelink then
			return '[[' .. sitelink .. '|' .. label .. ']]'
		end
		return label
	end,
	
	flag = function( qid )
		-- P41 is the property for the flag at Commons
		local values = findValues( loadStatements(qid, 'P41' ) )
		if #values == 0 then
			return ''
		end
		return values[1]
	end,
	
	coa = function( qid )
		-- P94 is the property for the coat of arms at Commons
		local values = findValues( loadStatements(qid, 'P94' ) )
		if #values == 0 then
			return ''
		end
		return values[1]
	end
}

-- @var table box holds the table, aka our "this"
local box = {}

-- get this and format it according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return nil
function box.this( frame )
	local qid = findQID( frame.args )
	if qid then
		local entity = qid and mw.wikibase.getEntity( qid ) or mw.wikibase.getEntity()
		qid = entity['id']
	end
	return build( qid, findNotQID( frame.args ) )
end

-- get parent and format it according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return nil
function box.parent( frame )
	return formatStatements(
		loadStatements( findQID( frame.args ), 'P131', 'P150' ),
		findNotQID( frame.args )
	)
end

-- get parts and format them according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return string
function box.parts( frame )
	return formatStatements(
		loadStatements( findQID( frame.args ), 'P527', 'P361' ),
		findNotQID( frame.args )
	)
end

-- get areas and format them according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return string
function box.areas( frame )
	return formatStatements(
		loadStatements( findQID( frame.args ), 'P150', 'P131' ),
		findNotQID( frame.args )
	)
end

-- get neighbors and format them according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return string
function box.neighbors( frame )
	return formatStatements(
		loadStatements( findQID( frame.args ), 'P47', 'P47' ),
		findNotQID( frame.args )
	)
end

-- get siblings and format them according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return nil
function box.siblings( frame )
	local ids = findIds( loadStatements( findQID( frame.args ), 'P131', 'P150' ) )
	return formatStatements(
			(#ids == 0) and {} or loadStatements( 'Q' .. ids[1], 'P150', 'P131' ),
			findNotQID( frame.args )
		)
end

-- get nation and format it according to build directive
-- @param any frame provides alternate base entity and build directive
-- @return nil
function box.nation( frame )
	local qid = findQID( frame.args )
	local directive = findNotQID( frame.args )
	while qid do
		local nations = findIds( loadStatements( qid, 'P17', 'P150' ) )
		if #nations > 0 then
			return build( 'Q' .. nations[1], directive )
		end
		local ids = findIds( loadStatements( qid, 'P131', 'P150' ) )
		if #ids == 0 then
			return ''
		end
		qid = 'Q' .. ids[1]
	end

	return ''
end

local title = mw.title.getCurrentTitle()
if title:inNamespaces( 828, 829) then
	box._findQID = findQID
	box._findNotQID = findNotQID
	box._loadStatements = loadStatements
end

return box