Hopp til innhold

Modul:Official links

Fra Wikipedia, den frie encyklopedi

require('strict')

local contLang = mw.language.getContentLanguage()
local conf = require 'Module:Official links/conf'(contLang:getCode())

local labels = {}

local function buildList( pid, t  )
	if #t == 0 then
		return ''
	elseif #t == 1 then
		return t[1]
	end
	local last = table.remove(t)
	local str = table.concat(t, mw.message.newRawMessage(conf:g('initial-' .. pid .. '-combiner', 'initial-default-combiner')):plain())
	return mw.message.newRawMessage(conf:g('final-' .. pid .. '-combiner', 'final-default-combiner'), str, last):plain()
end

-- todo: messy solution, refactor
local function wrap( content, marker )
	if content == '' or content == nil then
		return nil
	end
	return '<span class="mw-collapsible mw-collapsed" id="mw-customcollapsible-'..marker..'"><span class="mw-collapsible-content">' .. content .. '</span>'
		.. ' <span class="mw-customtoggle-'..marker..'" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}" /></span>'
end

local function getEntityLabel( id )
	local entity = mw.wikibase.getEntity( id )
	if entity then
		return entity:getLabel()
	end
end

local function findEntityLabel( id )
	if not labels[id] then
		local label = getEntityLabel( id )
		if label then
			labels[id] = label -- labels is an outer structure
		end
	end
	return labels[id]
end

local mainFormatter = {}
mainFormatter['string'] = function( pid, datavalue )
	if datavalue['type'] ~= 'string' then
		return nil
	end
	return datavalue.value
end

local qualFormatter = {}
qualFormatter['wikibase-entityid'] = function( pid, datavalue )
	if datavalue['type'] ~= 'wikibase-entityid' then
		return nil
	end
	if datavalue.value['entity-type'] ~= 'item' then
		return nil
	end
	return findEntityLabel( 'Q'..datavalue.value["numeric-id"] )
end

local qualPrefer = {}
qualPrefer['wikibase-entityid'] = function( pid, datavalue )
	if datavalue['type'] ~= 'wikibase-entityid' then
		return nil
	end
	if datavalue.value['entity-type'] ~= 'item' then
		return nil
	end
	return conf:p( 'Q'..datavalue.value["numeric-id"] ) or false
end

local main = {}
main.P856 = {
	types = {
		snaktype = 'value',
		datatype = 'url',
	},
	formatter = mainFormatter['string']
}
main.P1019 = {
	types = {
		snaktype = 'value',
		datatype = 'url',
	},
	formatter = mainFormatter['string']
}
main.P1581 = {
	types = {
		snaktype = 'value',
		datatype = 'url',
	},
	formatter = mainFormatter['string']
}


local qual = {}
qual.P407 = {
	types = {
		snaktype = 'value',
		datatype = 'wikibase-item',
	},
	formatter = qualFormatter['wikibase-entityid'],
	preferred = qualPrefer['wikibase-entityid']
}

local qorder = {'P407'}

local p = {}

function p.findMainLinks(pid, qid)
	local head = {}
	local tail = {}
	local entity = mw.wikibase.getEntityObject( qid )
	-- to avoid deep tests
	if not entity or not entity.claims then
		return head, tail
	end
	local statements = entity.claims[pid]
	-- to avoid deep tests
	if not statements then
		return head, tail
	end
	for _, claim in ipairs( statements ) do
		-- to avoid deep tests
		if not claim then
			claim = {}
		end
		local valid = true
		if claim['type'] ~= 'statement' then
			valid = valid and false
		end
		if claim['rank'] == 'deprecated' then
			valid = valid and false
		end
		local mainsnak = claim.mainsnak or {}
		if not mainsnak or not main[pid] then
			valid = valid and false
		end
		if ((main[pid] and mainsnak.snaktype ~= main[pid].types.snaktype)
			or (main[pid] and mainsnak.datatype ~= main[pid].types.datatype))
		then
			valid = valid and false
		end
		if valid then
			local preferred = claim['rank'] == 'preferred'
			local mainStr = main[pid].formatter(pid, mainsnak.datavalue)
			local optionals = {}
			local qualifiers = claim.qualifiers or {}
			for _, qualid in ipairs( qorder ) do
				if qualifiers[qualid] then
					local items = {}
					for _, qualsnak in ipairs( qualifiers[qualid] ) do
						if qualsnak and qual[qualid] then
							if not (qualsnak.snaktype ~= qual[qualid].types.snaktype
								or qualsnak.datatype ~= qual[qualid].types.datatype)
							then
								items[1+#items] = qual[qualid].formatter(qualsnak.property, qualsnak.datavalue)
								preferred = preferred or qual[qualid].preferred(qualsnak.property, qualsnak.datavalue)
							end
						end
					end
					local text = buildList(qualid, items)
					if qualid == 'P407' then
						if not text or text == '' then
							-- this should never happen, unless it will be possible to add empty qualifiers
							text = mw.message.newRawMessage(conf:g('qualifier-'.. qualid..'-empty', 'qualifier-default-empty')):plain()
						end
						text = mw.message.newRawMessage(conf:g('ext-link-' .. claim['rank']), mainStr, text):plain()
					end
					optionals[1+#optionals] = text
				else
					local text = nil
					if qualid == 'P407' then
						text = conf:guess(mainStr)
					end
					if not text then
						text = mw.message.newRawMessage(
							conf:g('qualifier-'.. pid..'-missing-'..qualid,
								'qualifier-default-missing-'..qualid,
								'qualifier-default-missing')):plain()
					end
					optionals[1+#optionals] = mw.message.newRawMessage(conf:g('ext-link-' .. claim['rank']), mainStr, text):plain()
				end
			end
			if #optionals > 0 then
				mainStr = buildList(pid, optionals)
			end
			if preferred then
				head[1+#head] = mainStr
			else
				tail[1+#tail] = mainStr
			end
		end
	end
	return head, tail
end

function p.links( frame )
	local items = {}
	local counts = {}
	for _,v in ipairs(frame.args) do
		local _, _, ch, num= v:find("([pP])(%d+)")
		if ch then
			local pid = ch:upper()..num
			local label = findEntityLabel( pid )
			if not counts[pid] then
				counts[pid] = 0
			end
			if label then
				local head, tail = p.findMainLinks(pid)
				if (head and #head > 0) or (tail and #tail > 0) then
					counts[pid] = counts[pid] + 1
				end
				if head and #head > 0 then
					items[1+#items] = { contLang:ucfirst( label ), buildList('', head), wrap(buildList('', tail), pid) }
				elseif tail and #tail > 0 then
					items[1+#items] = { contLang:ucfirst( label ), buildList('', tail) }
				end
			end
		end
	end
	for i,v in ipairs(items) do
		items[i] = mw.message.newRawMessage(
			((#v >=3 and #v[3])
				and conf:g(i==1 and 'first-list-item-with-additional' or 'rest-list-item-with-additional')
				or conf:g(i==1 and 'first-list-item' or 'rest-list-item')),
			unpack(v))
		:plain()
	end
	local cats = {}
	for k,v in pairs(counts) do
		cats[1+#cats] = '[[Category:' .. mw.message.newRawMessage(conf:g(counts[k]==0 and 'cat-exclusion' or 'cat-inclusion'), findEntityLabel( k )):plain() .. ']]'
	end
	if #items > 0 then
		return table.concat(items, "\n") .. table.concat(cats, "")
	end
	return "''" .. mw.message.newRawMessage(conf:g('no-links-available')):plain() .. "''" .. table.concat(cats, "")
end

return p