Moduł:Brudnopis/Paweł Ziemian/Kontrola autorytatywna

Z Wikipedii, wolnej encyklopedii

Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Brudnopis/Paweł Ziemian/Kontrola autorytatywna/opis

require("strict")

local resources = {
	title = "[[Pomoc:Kontrola autorytatywna|Kontrola autorytatywna]]",
	otherTitle = "Identyfikatory zewnętrzne",
	catMissingLabel = '[[Kategoria:Kontrola autorytatywna potrzebuje polskiej etykiety]]',
	editLabelLink = '<span class="wdlink">&#x5B;[[:d:%s|<span  title="Brak polskiej etykiety">e</span>]]&#x5D;</span>',
	fallbackLabels = { "en", "de", "fr", "it", "cs", "lt", "pt", "es" },
	nativeTypes = { "P31", "P279" },
	-- type descriptions
	descriptions = {
		p = "osoba",
		k = "organizacja",
		v = "wydarzenie",
		w = "dzieło",
		s = "słowo kluczowe",
		g = "obiekt geograficzny",
	},
	bonus = {
		"P402",  -- identyfikator relacji OpenStreetMap
		
		"P2038", -- identyfikator ResearchGate
		"P1053", -- ResearcherID
		"P3829 Publons", -- identyfikator autora w Publons
		"P3124", -- identyfikator osoby w bazie „Ludzie nauki”
		
		--"P428",  -- skrót nazwiska botanika wg IPNI
		"P2036", -- African Plant Database;
		"P838 BioLib",  -- BioLib,
		"P830 [[Encyclopedia of Life|EoL]]",
		"P6177 EUNIS", -- EUNIS ID, (lub P6681 ?) 
		"P1747", -- Flora of China,
		"P1727", -- Flora of North America,
		"P6094", -- FloraWeb,
		"P846 GBIF",  -- Global Biodiversity Information Facility
		"P1421 GRIN",
		"P3151", -- iNaturalist,
		"P961 [[International Plant Names Index|IPNI]]",
		"P815 [[Integrated Taxonomic Information System|ITIS]]",
		"P685 NCPI",  -- NCBI,
		"P6034", -- Plant Finder,
		"P1070", -- PlantList,
		"P5037", -- Plants of the World,
		"P3105 Tela Botanica",
		"P960",  -- Tropicos,
		"P1772 USDA PLANTS", -- USDA PLANTS
		
		--"P640",  -- identyfikator Léonore
		--"P651",  -- BPN
		--"P902",  -- identyfikator w HDS
		--"P886",  -- LIR
		--"P434",  -- identyfikator artysty w MusicBrainz
		--"P549",  -- identyfikator Ensembl Gene
		--"P1225", -- identyfikator National Archives
		--"P1157", -- identyfikator US Congress Bio
		--"P1362", -- identyfikator TLS
		--"P781",  -- Sikart
		--"P1248", -- KulturNav-id
		--"P2558", -- identyfikator autores.uy
		--"P2750", -- Photographers' Identities Catalog ID
		--"P830",
		--"P815",
		--"P685",
	}
}

local has = function (entityId, propertyId)
	return #mw.wikibase.getBestStatements(entityId, propertyId) > 0
end

local hasAny = function (entityId, properties)
	for i, v in ipairs(properties) do
		if has(entityId, v) then
			return true
		end
	end

	return false
end

local isHumanPerson = function(entityId)
	for i, v in ipairs(mw.wikibase.getBestStatements(entityId, "P31")) do
		if (v.mainsnak.snaktype == "value")
		and (v.mainsnak.datavalue.value["numeric-id"] == 5) then
			return true
		end
	end
	
	for i, v in ipairs(mw.wikibase.getBestStatements(entityId, "P21")) do
		if (v.mainsnak.snaktype == "value") then
			local id = v.mainsnak.datavalue.value["numeric-id"]
			if (id == 6581097) or (id == 6581072) then
				return true
			end
		end
	end
	
	return false
end

local sources = {
	{
		name     = "ISNI",
		hint     = "International Standard Name Identifier",
		property = "P213",
		link     = function(id)
			local linkId, x = string.gsub(id, " ", "")
			return "http://isni-url.oclc.nl/isni/"..linkId
		end,
		show     = function(id)
			local showId, x = string.gsub(id, " ", "&thinsp;")
			return showId				
		end,
	},
	{
		name     = "ORCID",
		hint     = "ORCID",
		property = "P496",
		link     = function(id)
			id = string.gsub(id, "-", "")
			return "http://orcid.org/"..string.sub(id, 1, 4).."-"..string.sub(id,5,8).."-"..string.sub(id,9,12).."-"..string.sub(id,13,16)
		end,
		show     = function(id)
			id = string.gsub(id, "-", "")
			return string.sub(id, 1, 4).."-"..string.sub(id,5,8).."-"..string.sub(id,9,12).."-"..string.sub(id,13,16)
		end,
	},
	{
		name     = "VIAF",
		hint     = "Virtual International Authority File",
		property = "P214",
		link     = function(id)
			return "http://viaf.org/viaf/"..id
		end,
	},
	{
		name     = "ULAN",
		hint     = ":en:Union List of Artist Names",
		property = "P245",
		link     = function(id)
			return "http://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid="..id
		end,
	},
	{
		name     = "Europeana",
		hint     = "Europeana",
		property = "P727",
		link     = function(id)
			return "http://www.europeana.eu/portal/record/"..id..".html"
		end,
	},
	{
		name     = "LCCN",
		hint     = "Library of Congress Control Number",
		property = "P244",
		link     = function(id)
			return "http://lccn.loc.gov/"..id
		end,
	},
	{
		name     = "GND",
		hint     = "Gemeinsame Normdatei",
		property = "P227",
		link     = function(id)
			return "http://d-nb.info/gnd/"..id
		end,
	},
	{
		name     = "NDL",
		hint     = ":de:Web NDL Authorities",
		property = "P349",
		link     = function(id)
			return "http://id.ndl.go.jp/auth/ndlna/"..id
		end,
	},
	{
		name     = "LIBRIS",
		hint     = "LIBRIS",
		property = "P5587",
		link     = function(id)
			return "https://libris.kb.se/katalogisering/"..id
		end,
	},
	{
		name     = "SELIBR",
		hint     = "LIBRIS",
		property = "P906",
		disable  = function(entityId)
			return has(entityId, "P5587")
		end,
		link     = function(id)
			local x = mw.title.new("Module:Kontrola autorytatywna/P906/enabled").id
			return "http://libris.kb.se/auth/"..id
		end,
	},
	{
		name     = "BnF",
		hint     = "Biblioteka Narodowa Francji",
		property = "P268",
		link     = function(id)
			return "http://catalogue.bnf.fr/ark:/12148/cb"..id
		end,
	},
	{
		name     = "SUDOC",
		hint     = "Système Universitaire de Documentation",
		property = "P269",
		link     = function(id)
			return "http://www.idref.fr/"..id
		end,
	},
	{
		name     = "SBN",
		hint     = ":it:Servizio bibliotecario nazionale",
		property = "P396",
		link     = function(id)
			return "http://id.sbn.it/af/"..id
		end,
	},
	{
		name     = "NLA",
		hint     = "Biblioteka Narodowa Australii",
		property = "P409",
		link     = function(id)
			return "http://nla.gov.au/anbd.aut-an"..id
		end,
	},
	{
		name     = "BNCF",
		hint     = ":it:Biblioteca Nazionale Centrale di Firenze",
		property = "P508",
		link     = function(id)
			return "http://thes.bncf.firenze.sbn.it/termine.php?id="..id
		end,
	},
	{
		name     = "NKC",
		hint     = "Biblioteka Narodowa Republiki Czeskiej",
		property = "P691",
		link     = function(id)
			return "http://aut.nkp.cz/"..id
		end,
	},
	{
		name     = "DBNL",
		hint     = ":nl:Digitale Bibliotheek voor de Nederlandse Letteren",
		property = "P723",
		link     = function(id)
			return "http://www.dbnl.org/auteurs/auteur.php?id="..id
		end,
	},
	{
		name     = "RSL",
		hint     = ":ru:Российская государственная библиотека",
		property = "P947",
		link     = function(id)
			return "http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request="..id
		end,
	},
	{
		name     = "BNE",
		hint     = "Hiszpańska Biblioteka Narodowa",
		property = "P950",
		link     = function(id)
			return "http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id="..id
		end,
	},
	{
		name     = "BNR",
		hint     = "Biblioteka Narodowa Rumunii",
		property = "P1003",
		link     = function(id)
			return "http://alephnew.bibnat.ro:8991/F?func=find-b&request="..id.."&find_code=SYS&adjacent=Y&local_base=NLR10"
		end,
	},
	{
		name     = "NTA",
		hint     = "Holenderska Biblioteka Narodowa",
		property = "P1006",
		link     = function(id)
			--return "http://opc4.kb.nl/PPN?PPN="..id
			return "http://data.bibliotheken.nl/doc/thes/p"..id
		end,
	},
	{
		name     = "BIBSYS",
		hint     = "BIBSYS",
		property = "P1015",
		link     = function(id)
			return "https://authority.bibsys.no/authority/rest/authorities/html/"..id
		end,
	},
	{
		name     = "CALIS",
		hint     = ":zh:中国高等教育文献保障系统",
		property = "P270",
		link     = function(id)
			return "http://opac.calis.edu.cn/aopac/ajsp/detail.jsp?actionfrom=1&actl=CAL++"..id.."%23"
		end,
	},
	{
		name     = "CiNii",
		hint     = ":jp:CiNii",
		property = "P271",
		link     = function(id)
			return "http://ci.nii.ac.jp/author/"..id
		end,
	},
	{
		name     = "Open Library",
		hint     = ":en:Open Library",
		property = "P648",
		link     = function(id)
			return "https://openlibrary.org/books/"..id
		end,
	},
	{
		name     = "NLP",
		hint     = "Biblioteka Narodowa (Warszawa)",
		property = "P7293",
		link     = function(id)
			return "http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=01&IM=04&NU=01&WI="..id
		end,
	},
	{
		name     = "NLP",
		hint     = "Biblioteka Narodowa (Warszawa)",
		property = "P1695",
		disable  = function(entityId)
			return has(entityId, "P7293")
		end,
		link     = function(id)
			if id:byte(1) ~= 65 then
				local x = mw.title.new("Module:Kontrola autorytatywna/P1695/invalid").id
				return "http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=01&IM=04&NU=01&WI="..id
			end
			
			local y = mw.title.new("Module:Kontrola autorytatywna/P1695/enabled").id
			return "http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=01&IM=05&TX=&NU=01&WI="..id
		end,
	},
	{
		name     = "NUKAT",
		hint     = "NUKAT",
		property = "P1207",
		link     = function(id)
			local good = string.match(id, "^[npst] %d%d%d%d%d%d%d%d%d%d$")
					or string.match(id, "^[npst]  %d%d%d%d%d%d%d%d$")
			if not good then
				local prefix = string.sub(id,1,1)
				local number = string.sub(id,2)
				local infix = #number == 8 and "%20%20" or "%20"
				good = prefix..infix..number
			end
			
			local linkid, x = string.gsub(good, ' ', '%%20')
			return "http://nukat.edu.pl/aut/"..linkid
		end,
	},
	{
		name     = "OBIN",
		hint     = "Dictionary of National Biography",
		property = "P1415",
		link     = function(id)
			return "https://doi.org/10.1093/ref:odnb/"..id
		end,
	},
	{
		name     = "NLI",
		hint     = "Biblioteka Narodowa Izraela",
		property = "P949",
		link     = function(id)
			return "http://uli.nli.org.il/F/?func=direct&doc_number="..id.."&local_base=nlx10"
		end,
	},
	{
		name     = "PTBNP",
		hint     = "Biblioteka Narodowa Portugalii",
		property = "P1005",
		link     = function(id)
			return "http://urn.bn.pt/nca/unimarc-authorities/txt?id="..id
		end,
	},
	{
		name     = "CANTIC",
		hint     = ":ca:Catàleg d'autoritats de noms i títols de Catalunya",
		property = "P1273",
		link     = function(id)
			return "http://cantic.bnc.cat/registres/CUCId/"..id
		end,
	},
	{
		name     = "LNB",
		hint     = "Biblioteka Narodowa Łotwy",
		property = "P1368",
		link     = function(id)
			return "https://kopkatalogs.lv/F?func=direct&local_base=lnc10&doc_number="..id.."&P_CON_LNG=ENG"
		end,
	},
	{
		name     = "NSK",
		hint     = ":hr:Nacionalna i sveučilišna knjižnica u Zagrebu",
		property = "P1375",
		link     = function(id)
			return "http://katalog.nsk.hr/F/?func=direct&doc_number="..id.."&local_base=nsk10"
		end,
	},
	{
		name     = "BNA",
		hint     = ":es:Biblioteca Nacional de la República Argentina",
		property = "P3788",
		link     = function(id)
			return "http://catalogo.bn.gov.ar/F/?func=direct&doc_number="..id.."&local_base=BNA10"
		end,
	},
	{
		name     = "CONOR",
		hint     = ":sl:CONOR",
		property = "P1280",
		link     = function(id)
			return "https://plus.cobiss.si/opac7/conor/"..id
		end,
	},
	{
		name     = "BNC",
		hint     = ":es:Biblioteca Nacional de Chile",
		property = "P1890",
		link     = function(id)
			return "http://www.bncatalogo.cl/F?func=direct&local_base=red10&doc_number="..id
		end,
	},
	{
		name     = "ΕΒΕ",
		hint     = "Grecka Biblioteka Narodowa",
		property = "P3348",
		link     = function(id)
			return "http://data.nlg.gr/resource/authority/record"..id
		end,
	},
	{
		name     = "BLBNB",
		hint     = "Brazylijska Biblioteka Narodowa",
		property = "P4619",
		link     = function(id)
			return "http://acervo.bn.br/sophia_web/autoridade/detalhe/"..id
		end,
	},
	{
		name     = "KRNLK",
		hint     = "Biblioteka Narodowa Korei",
		property = "P5034",
		link     = function(id)
			return "https://nl.go.kr/authorities/resource/"..id
		end,
	},
	{
		name     = "LIH",
		hint     = "Litewska Biblioteka Narodowa im. Martynasa Mažvydasa",
		property = "P7699",
		link     = function(id)
			return "https://lnb.libis.lt/simpleSearch.do?doSearch=1&AI001="..mw.uri.encode(id,"PATH")
		end,
	},
	{
		name     = "NSZL",
		hint     = "Państwowa Biblioteka Széchényiego",
		property = "P3133",
		link     = function(id)
			return "http://nektar.oszk.hu/auth/"..id
		end,
	},
	{
		name     = "RISM",
		hint     = "Répertoire International des Sources Musicales",
		property = "P5504",
		link     = function(id)
			return "https://opac.rism.info/search?id="..id
		end,
	},

	-- Zawsze na końcu / Always last !!!
	{
		name     = "WorldCat",
		hint     = "WorldCat",
		property = "P7859",
		link     = function(id)
			return "http://www.worldcat.org/identities/"..id
		end,
	},
}

local getDescription = function (entityId, force)
	local needLabel = false
	local site = mw.wikibase.getSitelink(entityId)
	local label = mw.wikibase.getLabelByLang(entityId, 'pl')
	if not label then
		for i, l in ipairs(resources.fallbackLabels) do
			label = mw.wikibase.getLabelByLang(entityId, l)
			if label then
				needLabel = true
				break
			end
		end
	end
		
	if site and label then
		return "[["..site.."|"..label.."]]", needLabel
	elseif site then
		return "[["..site.."]]", needLabel
	elseif label then
		return label, needLabel
	elseif force then
		return entityID, true
	end
end

local findDescription = function (entityId, sourceProps)
	local alt = nil
	for i, prop in ipairs(sourceProps) do
		for j, v in ipairs(mw.wikibase.getBestStatements(entityId, prop)) do
			if (v.mainsnak.snaktype == "value")
			and (v.mainsnak.datatype == "wikibase-item") then
				local qid = v.mainsnak.datavalue.value.id
				--	or "Q"..v.mainsnak.datavalue.value["numeric-id"]
				local description, needLabel = getDescription(qid, false)
				if description and not needLabel then
					return description, false
				end

				alt = alt or description
			end
		end
	end
	
	return alt, alt
end

local insertHeader = function(title, entityId, result, before, after)
	
	local determineDnbType = function()
		if isHumanPerson(entityId) then
			return "p"
		end
		
		-- pozostałe testy
		if hasAny(entityId, { "P1687", "P1963" }) then
			return "s"
		elseif hasAny(entityId, {"P27", "P26", "P25", "P22", "P40", "P106", "P1317"}) then
			return "p"
		elseif hasAny(entityId, {"P50", "P170", "P86", "P87", "P676", "P435"}) then
			return "w"
		elseif hasAny(entityId, {"P112", "P159", "P169", "P488", "P355", "P740"}) then
			return "k"
		elseif hasAny(entityId, {"P150", "P610", "P1589", "P85", "P35", "P36", "P47", "P984", "P474", "P982", "P300", "P901"}) then
			-- P625 cannot be used, there are some organizations, events, and even persons with this property
			return "g"
		end
	end
	
	local editLabelLink = ""
	local typClass = "normdaten-andere"
	local description = ''
	local needLabel = false
	if entityId then
		local typ = determineDnbType() or "fehlt"
		typClass = "normdaten-typ-"..typ
		if entityId ~= mw.wikibase.getEntityIdForCurrentPage() then
			description, needLabel = getDescription(entityId, true)
			if needLabel then
				editLabelLink = string.format(resources.editLabelLink, entityId)
			end
		elseif typ == 'p' then
			-- "człowiek" -> "osoba"
			description = resources.descriptions[typ]
		else
			description, needLabel = findDescription(entityId, resources.nativeTypes)
			description = description or resources.descriptions[typ]
		end
	end
	
	if needLabel then
		description = description..resources.catMissingLabel
	end

	if description and (#description > 0) then
		title = title.."&nbsp;(" .. description.. ")" .. editLabelLink
	end
	
	table.insert(result, 1, '<div class="'..typClass..'">')
	table.insert(result, 2, title..":")
	if before then table.insert(result, 3, before) end
	if after then table.insert(result, after) end
	table.insert(result,"</div>")
end

local formats = {
	classic = function(info, identifiers)
		local result = {}
		table.insert(result, "[[")
		table.insert(result, info.hint)
		table.insert(result, "|")
		table.insert(result, info.name)
		table.insert(result, "]]")
		local show = info.show or function(id) return id end
		for i, id in ipairs(identifiers) do
			table.insert(result, (i == 1) and ":" or ",")
			table.insert(result, "&thinsp;<span class=\"uid\">[")
			table.insert(result, info.link(id))
			table.insert(result, " ")
			table.insert(result, show(id))
			table.insert(result, "]</span>")
		end
		
		return table.concat(result, "")
	end,
	
	mini = function(info, identifiers)
		local result = {}
		if #identifiers == 1 then
			-- simple link with authority name
			local id = identifiers[1]
			table.insert(result, "[")
			table.insert(result, info.link(id))
			table.insert(result, " ")
			table.insert(result, string.format(info.format or "<span title=\"%s\">%s</span>", id, info.name))
			table.insert(result, "]")
			return table.concat(result, "")
		end

		table.insert(result, info.name)
		for i, id in ipairs(identifiers) do
			table.insert(result, (i == 1) and ":" or ",")
			table.insert(result, "&thinsp;[")
			table.insert(result, info.link(id))
			table.insert(result, " ")
			table.insert(result, string.format("<span title=\"%s\">%s</span>", id, tostring(i)))
			table.insert(result, "]")
		end
		
		return table.concat(result, "")
	end,
}
	
local show = function(entityId, argStyle)

	local identifiers = function (info)
		local result = {}

		if info.disable and info.disable(entityId) then
			return result;
		end

		for i, v in ipairs(mw.wikibase.getBestStatements(entityId, info.property)) do
			if v.mainsnak.snaktype == "value" then
				table.insert(result, v.mainsnak.datavalue.value)
			end
		end

		return result
	end
	
	local result = {}
	local formatItems = formats[argStyle] or formats.classic
	for i, info in ipairs(sources) do
		local list = identifiers(info)
		if #list > 0 then
			table.insert(result, "<li>"..formatItems(info, list).."</li>")
		end
	end
	
	if #result > 0 then
		insertHeader(resources.title, entityId, result, "<ul>", "</ul>")
		return table.concat(result, "");
	end
end

local findPropertyDescription = function(pid)
	local description, needLabel = findDescription(pid, {"P1629"})
	if not description or (#description == 0) or needLabel then
		description, needLabel = getDescription(pid, false)
		if not description or (#description == 0) or needLabel then
			mw.log("KA "..pid..": Brak opisu cechy")
		else
			mw.log("KA "..pid..": Brak elementu 'dedykowany typ dla' (P1629) w opisie cechy")
		end
	end
	
	return description, needLabel
end

return {

["Dokumentacja"] = function(frame)
	local result = {}
	table.insert(result, "{| class=wikitable\n!nazwa\n!cecha\n!dostawca\n")
	for i, v in ipairs(sources) do
		if i > 0 then
			table.insert(result, "|-\n")
		end
		
		table.insert(result, "|")
		table.insert(result, v.name)
		table.insert(result, "\n")
		
		table.insert(result, "|[[:d:Property:")
		table.insert(result, v.property)
		table.insert(result, "|")
		table.insert(result, v.property)
		table.insert(result, "]]\n")
		
		table.insert(result, "|[[")
		table.insert(result, v.hint)
		table.insert(result, "]]\n")
	end
	
	table.insert(result, "|-\n")
	table.insert(result, '!colspan="3"| Identyfikatory zewnętrzne\n')
	for i, b in ipairs(resources.bonus) do
		local pid, name = mw.ustring.match(b, "^(P[0-9]+) +(.+)$")
		if not pid then
			pid = b
		end
		
		local description, needLabel = findPropertyDescription(pid)
		if name or (description and not needLabel) then
			table.insert(result, "|-\n")

			table.insert(result, "|")
			table.insert(result, name or '')
			table.insert(result, "\n")
			
			table.insert(result, "|[[:d:Property:")
			table.insert(result, pid)
			table.insert(result, "|")
			table.insert(result, pid)
			table.insert(result, "]]\n")
			
			table.insert(result, "|")
			table.insert(result, description or '')
			table.insert(result, "\n")
		end
	end
	table.insert(result, "|}")
	
	return table.concat(result, "")
end,
	
["Pokaż"] = function (frame)
	
	local args = frame.args
	local parent = frame:getParent().args
	
	local entityId = mw.wikibase.getEntityIdForCurrentPage()
	if (mw.title.getCurrentTitle() ~= 0) and (args[1] or parent[1]) then
		entityId = args[1] or parent[1] or entityId
	end

	if not entityId then
		return
	end
	
	local argStyle = args.style
	
	local result = {
		-- typical result
		show(entityId, argStyle)	
	}
	
	local group = false
	local idGroupOfHumans = 'Q16334295'
	for i, v in ipairs(mw.wikibase.getBestStatements(entityId, "P31")) do
		if v.mainsnak.snaktype == "value" then
			local id = v.mainsnak.datavalue.value.id
			if id == idGroupOfHumans then
				group = true
				break
			end
			
			local status, r = pcall(mw.wikibase.getReferencedEntityId, id, 'P279', { idGroupOfHumans })
			if not status then
				-- za dużo wywołań, max 3
				break
			end
			
			if r then
				group = true
				break
			end
		end
	end

	if group then
		local p527 = mw.wikibase.getBestStatements(entityId, "P527")
		-- dodawaj nie więcej niż 5 osób dodatkowo
		if (#p527 > 0) and (#p527 <= 5) then
			for i, v in ipairs(p527) do
				if v.mainsnak.snaktype == "value" then
					local id = v.mainsnak.datavalue.value.id
					--	or "Q"..tostring(v.mainsnak.datavalue.value["numeric-id"])
					if isHumanPerson(id) then
						local s = show(id, argStyle)
						if s then
							table.insert(result, s)
						end
					end
				end
			end
		end
	end
	
	-- czas na bonus
	local genericPrinter = false -- lazy loaded
	local bonus = {}
	for i, b in ipairs(resources.bonus) do
		local pid, name = mw.ustring.match(b, "^(P[0-9]+) +(.+)$")
		if not pid then
			pid = b
		end
		
		local prop = mw.wikibase.getBestStatements(entityId, pid)
		if prop and (#prop > 0) then
			local description = name
			local needLabel = false
			if not description then
				description, needLabel = findPropertyDescription(pid)
			end
			if description and (#description > 0) and not needLabel then
				local expectedPattern = "^%[(%S+) (.-)%]$"
				local uids = {}
				for j, p in ipairs(prop) do
					-- lazy loading once
					genericPrinter = genericPrinter or require("Moduł:Wikidane/format/string")
					local s = genericPrinter.format(p.mainsnak, {})
					if s and (#s > 0) then
						local link, id = mw.ustring.match(s, expectedPattern)
						if link then
							table.insert(uids, s)
						end
					end
				end
				if #uids > 0 then
					local info = {
						show = function(s)
							local link, id = mw.ustring.match(s, expectedPattern)
							return id
						end,
						link = function(s)
							local link, id = mw.ustring.match(s, expectedPattern)
							return link
						end,
					}
					local hint, name = mw.ustring.match(description, "^%[%[(.-)|(.-)%]%]$")
					if hint then
						info.hint = hint
						info.name = name
					else
						local sitelink = mw.ustring.match(description, "^%[%[(.-)%]%]$")
						if name then
							info.hint = sitelink
							info.name = sitelink
						else
							info.hint = ":d:Property:"..pid
							info.name = description
						end
					end
					local formatItems = formats[argStyle] or formats.classic
					table.insert(bonus, "\n*"..formatItems(info, uids))
				end
			end
		end
	end
	
	if #bonus > 0 then
		insertHeader(resources.otherTitle, (#result == 0) and entityId, bonus, "\n", "\n")
		for i, b in ipairs(bonus) do
			table.insert(result, b)
		end
	end

	if #result > 0 then
		table.insert(result, 1, '<div id="normdaten" class="catlinks">')
		table.insert(result, "</div>")
		return table.concat(result, "")
	end
end,

["Zestaw"] = function (frame)
	local t = frame.args["tytuł"] or "[[Kontrola autorytatywna]]"
	local e = frame.args["pusto"]
	local sd = require("Module:Wikidane/select")
	local f = require("Module:Wikidane/format")
	local result = {}
	local i = 1
	while true do
		local p = frame.args[i]
		if not p then
			break
		end
		
		local pid, qid, prop = sd.selectProperty(p, {})
		if qid then
			local ppid, pqid, pprop = sd.selectProperty("P1629", {}, pid)
			if pqid then
				local s = "\n*"..f.run(frame, ppid, pprop)..":&nbsp;"..f.run(frame, pid, prop)
				table.insert(result, s)
			end
		end
		
		i = i + 1
	end
	
	if #result > 0 then
		table.insert(result, 1, '<div class="catlinks">')
		table.insert(result, 2, t)
		local pid, qid, prop = sd.selectProperty("P31", {}, nil, 1)
		table.insert(result, 3, qid and (" ("..f.run(frame, pid, prop).."):") or ":")
		table.insert(result, "</div>")
		return table.concat(result)
	end
	
	return e
end,

}