Přeskočit na obsah

Modul:Wikidata

Z Wikicest

Hlavní modul pro práci s daty na Wikidatech. Byl převzat z české Wikipedie.

Modul je rozdělen do submodulů:

Viz též seznam šablon, které tento modul využívají.

Použití

[editovat]

Do šablony vložte {{#invoke:Wikidata|funkce|parametry = jako v šablonách}}.

Parametry a funkce označené hvězdičkou (*) nejsou plně podporované a není zatím doporučeno je využívat. Naopak parametry či funkce označené křížkem (†) jsou zastaralé a mohou být v brzké době odstraněny.

Přehled všech funkcí a parametrů
Funkce Popis funkce Parametr Povinný Popis parametru
formatStatements získá data, vybere tvrzení, přefiltruje, seřadí a zformátuje jejich hodnoty a vrátí jejich seznam id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
property ano identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), jejíž hodnoty se mají zformátovat a zobrazit
addlink ne pokud je „true“, na konci dat z repozitáře se objeví (e) odkazující přímo na vlastnost
addclass ne pokud je „false“, potlačí obalení údajů CSS třídou (používat jen ve výjimečných případech)
value-formatter ne submodul modulu Wikidata/Formatters (jeho podstránka), která se použije pro formátování hodnot, pokud výchozí submodul není vyhovující (seznam, návod)
limit ne maximální počet hodnot, které se v seznamu zobrazí
rank ne nutné postavení hodnoty v rámci tvrzení;
může být all – použijí se všechna tvrzení; best – použijí se buď pouze tvrzení, která mají preferované postavení, nebo pouze ta s normálním postavením, pokud žádné preferované není; valid (implicitní) – použijí se jak preferovaná, tak normálně postavená tvrzení; preferred, normal, deprecated – použijí se pouze tvrzení s odpovídajícím postavením
withtarget ne hodnota, jíž mají nabývat hledaná tvrzení (užitečné zejména pro funkce getCount a getQualifier)
withqualifier ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), která musí být přiřazena dané hodnotě v tvrzení jako vymezení
withqualifiervalue ne hodnota, jíž má nabývat vlastnost vymezení daná parametrem „withqualifier“
withoutqualifier ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), která nesmí být přiřazena dané hodnotě v tvrzení jako vymezení
withoutqualifiervalue ne hodnota, jíž nemá nabývat vlastnost vymezení daná parametrem „withoutqualifier“
withunit ne identifikátor položky na Wikidatech
withlabel*
withsitelink*
withlang ne kód jazyka, ve kterém mají být hodnoty jednojazyčného textu
date ne datum ve formátu YYYY-MM-DD nebo „#now“ (dnešní datum), ke kterému mají být tvrzení platná
sort ne způsob, jakým změnit implicitní pořadí jednotlivých hodnot; hodnota parametru odpovídá čárkou odděleným podstránkám modulu Wikidata/Sorters
invert ne pokud je „true“ a je zadán způsob řazení („sort“), řazení bude sestupné, nikoliv výchozí vzestupné
pattern ne pokud je typ hodnoty řetězec, je toto vzor pro zformátování, přičemž „$1“ nahrazuje daný řetězec
autoformat ne pokud je „true“ a typ hodnoty řetězec, modul se na stránce dotyčné vlastnosti pokusí najít náhradu za pattern (Šablona:Property) a aplikuje ji
precision ne přizpůsobení formátu časových údajů (pokud je skutečná přesnost nižší, formát se přizpůsobí jí); 11 – 30. října 2024, 10 – říjen 2024, 9 – 2024 atd.
somevalue ne pokud je vyplněný, modul bude zobrazovat i speciální hodnotu „neznámá hodnota“ s tímto textem
novalue ne pokud je vyplněný, modul bude zobrazovat i speciální hodnotu „bez hodnoty“ s tímto textem
showqualifier ne čárkou oddělené identifikátory vlastností na Wikidatech (písmeno „p“ následované číslicemi nebo „time“), které se zobrazí v závorce za hodnotou, pokud jsou dané hodnotě jako vymezení přiřazeny
showsource ne pokud je „true“, k datům z repozitáře se přidají reference
max_ref ne maximální počet referencí, které se mají zobrazit
showmore ne pokud je hodnota „true“, tak se v případě, že existuje více hodnot, než kolik povoluje limit, zobrazí na konci jejich seznamu text „… více na Wikidatech“ s odkazem přímo na vlastnost
list ne pokud je hodnota „ul“ nebo „ol“, hodnoty budou vráceny jako HTML seznam („ol“ – číslovaný, „ul“ – odrážkový)
separator ne znaky, jimiž se v seznamu oddělí jednotlivé hodnoty, kromě předposlední a poslední (implicitně čárka, neplatí pro HTML seznam)
conjunction ne znaky, jimiž se v seznamu oddělí předposlední a poslední hodnota (implicitně spojka „a“, neplatí pro HTML seznam)
qualifiers ... ne takto uvozený argument (např. „qualifiers precision“) bude použit pro výběr a formátování vymezení
showtargetdata* ne podobné jako „showqualifier“, ovšem data se místo z vymezení získávají z cílové položky
targetdate* ne podobné jako „date“, vztahuje se k údajům cílové položky
formatStatementsFromLua funkce, kterou používají pouze jiné moduly a která je jinak shodná s formatStatements entity ne tabulka s entitou, s níž má modul pracovat
getSitelink vrátí odkaz na článek daného projektu site / první nepojmenovaný ne zkratka projektu (implicitně „cswiki“)
pattern ne vzor pro zformátování odkazu, kde „$1“ je název odkazovaného článku (implicitně „$1“)
id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
addclass ne pokud je „true“, odkaz bude obalen CSS třídou
getLabel vrátí štítek položky v daném jazyce lang ne zkratka jazyka (implicitně „cs“)
id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
addclass ne pokud je „true“, štítek bude obalen CSS třídou
getDescription vrátí popisek položky v daném jazyce lang ne zkratka jazyka (implicitně „cs“)
id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
addclass ne pokud je „true“, popisek bude obalen CSS třídou
getAliases vrátí aliasy položky v daném jazyce lang ne zkratka jazyka (implicitně „cs“)
limit ne maximální počet aliasů, který se má zobrazit
id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
showmore ne jako u formatStatements
list ne
separator ne
conjunction ne
getBadges vrátí štítek odznaku přiřazeného danému odkazu na článek site ano zkratka projektu
id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž data se mají získat pro další práci s nimi (implicitně je to položka propojená s danou stránkou)
of ne identifikátor vlastnosti na Wikidatech (písmeno „p“ následované číslicemi), ze kterého se získá entita, kterou modul skutečně využije, tak, že se použije první nejlepší hodnota vlastnosti
page ne název stránky, jejíž položka se má použít pro získání údajů
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
getCount vrátí počet tvrzení podle daných kritérií všechny parametry pro filtrování
getCurrentId vrátí id položky, se kterou je stránka propojena
getId Vrátí id položky propojené se zadanou stránkou. Není-li propojená a jedná se o přesměrování, následuje jej (i rekurzivně). Nepodaří-li se, zkusí další stránky, pokud jich bylo zadáno víc. Nedostane-li parametry přímo, zpracuje parametry předané volající šabloně. první, druhý, ... nepojmenovaný ne název stránky na dané wiki (implicitně aktuální stránka)
wiki ne zkratka projektu (např. enwiki), z něhož uvedená stránka pochází
getRawValue použije stejná kritéria jako formatStatements, ovšem vrátí strojově čitelný (nezformátovaný) údaj všechny parametry pro filtrování
field ne pokud je typ hodnoty souřadnice, toto je její část, která se zobrazí; jedno z „latitude“, „longitude“, „precision“ a „globe“
getRawValueFromLua jako getRawValue, pro použití v jiném modulu entity ne tabulka s entitou, s níž má modul pracovat
getQualifier vrací hodnoty vymezení nalezeného tvrzení qualifier ano vlastnost vymezení, jejíž hodnoty mají být vráceny
qualifiers ... ne takto uvozený argument (např. „qualifiers withlang“) bude použit pro výběr (při filtrování) vymezení
stejné jako u funkce formatStatements
getRawQualifier aplikuje chování funkce getRawValue na getQualifier stejné jako u funkce getQualifier
formatEntity lokalizuje položku zadanou pomocí jejího identifikátoru (pokusí se vytvořit lokální odkaz a zobrazit štítek) id ne id položky, která se má zformátovat (jinak id položky, se kterou je stránka propojena)
entityExists zjistí, zda entita (položka, vlastnost atd.) s daným identifikátorem existuje (přesměrování se považuje za existující) id / první nepojmenovaný ano id položky, jejíž existenci zjišťujeme
ifexpr ne pokud je „true“, negativní hodnota bude vrácena jako „0“, jinak (výchozí chování) jako prázdný řetězec (užitečné, pokud ve wikitextu používáme funkci #ifexpr:, a ne #if:)
isValidEntityId zjistí, zda zadaný řetězec je platný identifikátor entity (položky, vlastnosti atd.) id / první nepojmenovaný ano řetězec, jehož validitu testujeme
ifexpr ne jako u entityExists
dumpWikidataEntity zobrazí entitu v čitelné podobě, užitečná pro ladění a zavádění nových funkcí, nepoužívá se v šablonách nebo článcích id ne identifikátor položky (písmeno „q“ následované číslicemi) nebo vlastnosti (písmeno „p“ následované číslicemi) na Wikidatech, jejíž entita se zobrazí (implicitně je to položka propojená s danou stránkou)

require 'strict'

local p = {}

local lib = require 'Modul:Wikidata/lib'
local i18n = mw.loadData('Modul:Wikidata/i18n')

local getArgs = (require 'Modul:Arguments').getArgs

local function outputBool(arg, ifexpr)
	local map
	if ifexpr then
		map = { [true] = 1, [false] = 0 }
	else
		map = { [true] = 1, [false] = '' }
	end
	return map[arg]
end

local function removeDuplicates(values)
	local TableTools = require 'Modul:TableTools'
	return TableTools.removeDuplicates(values)
end

local function getEntityIdFromStatements(statements)
	for _, statement in ipairs(statements) do
		if lib.IsSnakValue(statement.mainsnak) then
			if statement.mainsnak.datavalue.type ~= 'wikibase-entityid' then
				error(lib.raiseInvalidDatatype('getEntityIdFromStatements',
					statement.mainsnak.datatype, {'wikibase-item', 'wikibase-property'}))
			end
			local Formatters = require 'Modul:Wikidata/Formatters'
			return Formatters.getRawValue(statement.mainsnak, {})
		end
		break
	end
	return nil
end

local function getEntityIdFromEntity(entity, prop)
	local prop = mw.ustring.upper(prop)
	local statements = entity:getBestStatements(prop)
	return getEntityIdFromStatements(statements)
end

local function getEntityIdFromId(id, prop)
	local prop = mw.ustring.upper(prop)
	local statements = mw.wikibase.getBestStatements(id, prop)
	return getEntityIdFromStatements(statements)
end

local function getIdFromTitle(titleString, wiki)
	if wiki then
		return mw.wikibase.getEntityIdForTitle(titleString, wiki)
	end
	local title = mw.title.new(titleString)
	while title do
		local id = mw.wikibase.getEntityIdForTitle(title.prefixedText)
		if id then
			return id
		end
		title = title.redirectTarget
	end
	return nil
end

local function findEntityId(options)
	local id
	if options.entity and type(options.entity) == 'table' then
		id = options.entity.id
	end
	if not id and options.page then
		id = getIdFromTitle(options.page, options.wiki)
		if not id then
			return nil
		end
	end
	if not id then
		id = options.id or p.getCurrentId()
	end
	if id and options.of then
		id = getEntityIdFromId(id, options.of)
	end
	return id
end

local function findEntity(options)
	local entity
	if options.entity and type(options.entity) == 'table' then
		entity = options.entity
	end
	if not entity then
		if options.id then
			local id = options.id:upper()
			entity = mw.wikibase.getEntity(id)
			if entity and entity.id ~= id then
				mw.log(id .. ' je přesměrování na ' .. entity.id)
			end
		else
			if options.page then
				local id = getIdFromTitle(options.page, options.wiki)
				if id then
					entity = mw.wikibase.getEntity(id)
				end
			else
				entity = mw.wikibase.getEntity()
			end
		end
	end
	if options.of then
		if entity then
			local id = getEntityIdFromEntity(entity, options.of)
			if id then
				return mw.wikibase.getEntity(id)
			end
		end
		return nil
	end
	return entity
end

local function getSitelink(options)
	local id = findEntityId(options)
	if not id then
		return nil
	end

	local site = options.site or options[1]
	local sitelink = mw.wikibase.getSitelink(id, site)

	if not sitelink then
		return nil
	end

	if options.pattern then
		sitelink = lib.formatFromPattern(sitelink, options.pattern)
	end
	if lib.IsOptionTrue(options, 'addclass') then
		sitelink = lib.addWdClass(sitelink)
	end
	return sitelink
end

local function formatStatementAndData(statement, options)
	if not statement.type or statement.type ~= 'statement' then
		error(lib.formatError('unknown-claim-type', statement.type or '[neznámý]')) -- fixme: i18n
	end
	local Filterers = require 'Modul:Wikidata/Filterers'
	local Formatters = require 'Modul:Wikidata/Formatters'

	local result = { Formatters.getFormattedValue(statement.mainsnak, options) }
	local qualifiers
	if statement.qualifiers and options.showqualifier then
		local PropList = lib.textToTable(options.showqualifier)
		-- TODO: move this to a better place (config)
		local default_options = {
			isQualifier = true,
			label = 'short',
			nolink = lib.IsOptionTrue(options, 'nolink'),
			precision = 9,
		}
		for _, property in ipairs(PropList) do
			local property = mw.ustring.upper(property)
			local Values = {}
			local qualifiers_options = lib.augmentArgs(options, default_options, 'qualifiers ')
			if statement.qualifiers[property] then
				local Qualifiers = mw.clone(statement.qualifiers[property])
				qualifiers_options.property = property
				if not qualifiers_options.nolink then
					qualifiers_options.nolink = (Qualifiers[1].datatype == 'time')
				end
				Filterers.filterQualifiers(Qualifiers, qualifiers_options)
				for _, snak in ipairs(Qualifiers) do
					table.insert(Values, Formatters.getFormattedValue(snak, qualifiers_options))
				end
			elseif property == 'TIME' then
				local Data = {}
				-- TODO: factor out
				for key, array in pairs(lib.props) do
					for _, prop in ipairs(array) do
						for _, snak in ipairs(statement.qualifiers[prop] or {}) do
							if lib.IsSnakValue(snak) then -- dokud nebude jasné, jak to používat
								Data[key] = snak
								break
							end
						end
					end
				end
				if Data.begin or Data.ending then
					qualifiers_options.nolink = true
					table.insert(Values, lib.formatDateRange(Data, qualifiers_options))
				end
			end
			if #Values > 0 then
				result[property] = mw.text.listToText(
					removeDuplicates(Values),
					qualifiers_options.separator,
					qualifiers_options.conjunction)
			end
		end
	end
	if statement.references and lib.IsOptionTrue(options, 'showsource') then
		-- TODO: configure custom formatter
		local Module = require 'Modul:Wikidata/cite'
		result.ref = Module.formatReferences(statement.references, options) -- or table of references?
	end
	return result
end

local function formatStatement(statement, options)
	local data = formatStatementAndData(statement, options)
	local result = data[1]
	if options.isQualifier == true then
		return result
	end

	local qualifiers
	if statement.qualifiers and options.showqualifier then
		local PropList = lib.textToTable(options.showqualifier)
		local tmp = {}
		for _, prop in ipairs(PropList) do
			local prop = mw.ustring.upper(prop)
			if data[prop] then
				table.insert(tmp, data[prop])
			end
		end
		if #tmp > 0 then
			qualifiers = table.concat(tmp, i18n['qualifiers separator'])
		end
	end
	if not qualifiers and options.showtargetdata then
		local entity
		local Filterers = require 'Modul:Wikidata/Filterers'
		local Formatters = require 'Modul:Wikidata/Formatters'
		if lib.IsSnakValue(statement.mainsnak) then
			if statement.mainsnak.datavalue.type == 'wikibase-entityid' then
				entity = mw.wikibase.getEntity(Formatters.getRawValue(statement.mainsnak, {}))
			else
				error(lib.formatError('invalid-datatype', statement.mainsnak.property, statement.mainsnak.datatype, 'wikibase-item/wikibase-property'))
			end
		end
		if entity then
			local PropList = lib.textToTable(options.showtargetdata)
			local date
			local rank = 'best'
			if options.targetdate then
				if lib.isPropertyId(options.targetdate) then
					date = p.getRawValueFromLua{ entity = options.entity, property = options.targetdate }
				else
					date = options.targetdate
				end
				if date then
					rank = 'valid'
				end
			end
			local options = {
				addclass = false,
				autoformat = true,
				date = date,
				entity = entity,
				isQualifier = true,
				label = 'short',
				nolink = true,
				precision = 9,
				rank = rank,
				sort = {'date'},
			}
			local Snaks = {}
			for _, property in ipairs(PropList) do
				local result
				if mw.ustring.lower(property) == 'time' then
					local Data = {}
					for key, array in pairs(lib.props) do
						for _, prop in ipairs(array) do
							options.property = prop
							local Statements = Filterers.filterStatementsFromEntity(entity, options)
							for _, statement in ipairs(Statements) do
								Data[key] = statement.mainsnak
								break
							end
						end
					end
					if Data.begin or Data.ending then
						result = lib.formatDateRange(Data, options)
					end
				else
					options.property = property
					result = p.formatStatementsFromLua(options)
				end
				if result then
					table.insert(Snaks, result)
				end
			end
			if #Snaks > 0 then
				qualifiers = table.concat(Snaks, i18n['qualifiers separator'])
			end
		end
	end

	if qualifiers then
		if options.delimiter then
			result = result .. options.delimiter .. qualifiers
		else
			result = result .. ' (' .. qualifiers .. ')'
		end
	end
	if data.ref and data.ref ~= '' then
		return result .. data.ref .. lib.category('references')
	end
	return result
end

local function formatStatements(statements, options)
	local formattedStatements = {}
	for _, statement in ipairs(statements) do
		table.insert(formattedStatements, formatStatement(statement, options))
	end
	return formattedStatements
end

local function getStatements(id, options)
	if not id then
		return {}
	end
	local statements = mw.wikibase.getAllStatements(id, options.property:upper())
	local Filterers = require 'Modul:Wikidata/Filterers'
	Filterers.filterStatements(statements, options)
	return statements
end

local function prepareShowMore(options)
	if options.limit and lib.IsOptionTrue(options, 'showmore') then
		options.limit = options.limit + 1
		return true
	end
	return false
end

local function handleShowMore(values, limit, add_more)
	if add_more then
		if #values == limit then
			table.remove(values)
		else
			add_more = false
		end
	end
	return add_more
end

local function makeList(values, options, add_more, link)
	values = removeDuplicates(values) -- TODO: maybe make optional
	if add_more then
		local parts = mw.text.split(link, '#', true) -- b/c
		table.insert(values, mw.ustring.format(i18n['more-on-Wikidata'], parts[1], parts[2] or ''))
	end
	local text
	if options.list == 'ul' or options.list == 'ol' then
		local li = {}
		for _, val in ipairs(values) do
			table.insert(li, mw.ustring.format('<li>%s</li>', val))
		end
		text = mw.ustring.format('<%s class="wd">%s</%s>', options.list, table.concat(li), options.list)
	else
		text = mw.text.listToText(values, options.separator, options.conjunction)
		if lib.IsOptionTrue(options, 'addlink') then
			-- TODO: data-bridge-edit-flow
			text = mw.ustring.format('%s <sup class="wd-link">([[d:%s|e]])</sup>', text, link)
		end
		if tostring(options.addclass) ~= 'false' then
			text = lib.addWdClass(text)
		end
	end
	return text
end

local function getFormattedStatements(options)
	options.limit = tonumber(options.limit) --TODO default?
	local add_more = prepareShowMore(options)
	local id = findEntityId(options)
	local statements = getStatements(id, options)

	if #statements == 0 then return nil end
	add_more = handleShowMore(statements, options.limit, add_more)

	options.id = id
	-- Format statements and concat them cleanly
	local formattedStatements = formatStatements(statements, options)
	local property = mw.ustring.upper(options.property)
	local link = mw.ustring.format('%s#%s', id, property)
	local text = makeList(formattedStatements, options, add_more, link)
	if lib.IsOptionTrue(options, 'addcat') then
		text = text .. lib.category('used-property', property)
	end
	return text
end

local function getRawValue(options)
	if not options.rank then
		options.rank = 'best'
	end
	for _, statement in ipairs(p.getStatements(options)) do
		local Formatters = require 'Modul:Wikidata/Formatters'
		return Formatters.getRawValue(statement.mainsnak, options)
	end
	return nil
end

local function getQualifiers(args)
	if not args.qualifier then
		error(lib.formatError('param-not-provided', 'qualifier'))
	end
	if not args.rank then
		args.rank = 'best'
	end
	for _, statement in ipairs(p.getStatements(args)) do
		if statement.qualifiers then
			local qualifier_args = lib.augmentArgs(args, {}, 'qualifiers ')
			local qualifiers = mw.clone(statement.qualifiers[mw.ustring.upper(args.qualifier)] or {})
			local Filterers = require 'Modul:Wikidata/Filterers'
			Filterers.filterQualifiers(qualifiers, qualifier_args)
			return qualifiers
		end
		return {}
	end
	return {}
end

----- API pro šablony -----

function p.compareStatements(frame)
	local args = getArgs(frame, { frameOnly = true })
	return p._compareStatements(args)
end

function p.dumpWikidataEntity(frame)
	local args = getArgs(frame, { frameOnly = true })

	return mw.dumpObject( mw.wikibase.getEntity( args.id ) )
end

function p.getBadges(frame)
	local args = getArgs(frame, { frameOnly = true })
	local site = args.site
	if not site then
		error(lib.formatError('param-not-provided', 'site'))
	end
	local id = findEntityId(args)
	if not id then
		return nil
	end
	local Badges = {}
	local Formatters = require 'Modul:Wikidata/Formatters'
	for _, badge in ipairs(mw.wikibase.getBadges(id, site)) do
		table.insert(Badges, Formatters.formatRawValue(badge, 'wikibase-entityid'))
	end
	return table.concat(Badges, ', ')
end

function p.getLabel(frame)
	local args = getArgs(frame, { frameOnly = true })
	local id = findEntityId(args)
	if not id then
		return nil
	end
	local lang, label = args.lang
	if lang then
		label = mw.wikibase.getLabelByLang(id, lang)
	else
		label, lang = mw.wikibase.getLabelWithLang(id)
	end
	if not label then return nil end
	label = mw.text.nowiki(label)
	if lib.IsOptionTrue(args, 'addclass') then
		if lang ~= i18n.lang then
			return lib.addWdClass(lib.formatTextInLanguage(label, lang))
		else
			return lib.addWdClass(label)
		end
	end
	return label
end

function p.getDescription(frame)
	local args = getArgs(frame, { frameOnly = true })
	local id = findEntityId(args)
	if not id then
		return nil
	end
	local lang, description = args.lang
	if lang then
		description = mw.wikibase.getDescriptionByLang(id, lang)
	else
		description, lang = mw.wikibase.getDescriptionWithLang(id)
	end
	if not description then return nil end
	description = mw.text.nowiki(description)
	if lib.IsOptionTrue(args, 'addclass') then
		if lang ~= i18n.lang then
			return lib.addWdClass(lib.formatTextInLanguage(description, lang))
		else
			return lib.addWdClass(description)
		end
	end
	return description
end

function p.getAliases(frame)
	local args = getArgs(frame, { frameOnly = true })
	local entity = findEntity(args)
	local lang = args.lang or i18n.lang
	if not entity or not entity.aliases or not entity.aliases[lang] then
		return nil
	end

	args.limit = tonumber(args.limit)
	local add_more = prepareShowMore(args)
	local limit = args.limit
	local Aliases = {}
	for i, alias in ipairs(entity.aliases[lang]) do
		table.insert(Aliases, mw.text.nowiki(alias.value))
		if i == limit then
			break
		end
	end
	add_more = handleShowMore(Aliases, limit, add_more)
	return makeList(Aliases, args, add_more, entity.id)
end

function p.getId(frame)
	local args = getArgs(frame, {
		frameOnly = false,
		parentOnly = false,
		parentFirst = false,
	})

	if not args[1] then
		return mw.wikibase.getEntityIdForCurrentPage()
	end

	for _, titleString in ipairs(args) do
		local id = getIdFromTitle(titleString, args.wiki)
		if id then
			return id
		end
	end
	return nil
end

function p.getSitelink(frame)
	return getSitelink(getArgs(frame, { frameOnly = true }))
end

function p.formatStatements(frame)
	local args = getArgs(frame, { frameOnly = true })
	if args.value then return args.value end -- b/c for other wikis
	local parent_args = getArgs(frame, { parentOnly = true })
	local add
	if parent_args.item and not args.id then
		args.id = parent_args.item
		add = lib.category('arbitrary-data')
	end
	local value = getFormattedStatements(args)
	if add and value then
		return value .. add
	end
	return value
end

function p.formatTimespan(frame)
	local args = getArgs(frame, { frameOnly = true })
	local subargs = {}
	local data = {}
	local defaults = { sort = 'default' }
	for key in pairs{ start = true, ['end'] = true } do
		local prefix = key .. ' '
		if not args[prefix .. 'property'] then
			error('param-not-provided', prefix .. 'property')
		end
		subargs[key] = lib.augmentArgs(args, defaults, prefix)
		local statements = p.getStatements(subargs[key])
		if #statements > 0 then
			data[key] = statements
		end
	end
	if not data.start and not data['end'] then
		return nil
	end

	local out = {}
	if data.start and data['end'] then
		for _, startSt in ipairs(data.start) do
			for _, endSt in ipairs(data['end']) do
				local separator = ' – '
				-- TODO
				table.insert(
					out,
					mw.ustring.format('%s%s%s',
						formatStatement(startSt, subargs.start),
						separator,
						formatStatement(endSt, subargs['end'])
					)
				)
			end
		end
	else
		for key in pairs{ start = true, ['end'] = true } do
			for _, statement in ipairs(data[key] or {}) do
				table.insert(
					out,
					mw.ustring.format(
						args[key .. '-format'] or i18n.date[key],
						formatStatement(statement, subargs[key])
					)
				)
			end
		end
	end
	return makeList(out, args, false, '')
end

function p.formatStatementsFromTemplate(frame)
	local args = getArgs(frame, {
		frameOnly = false,
		parentOnly = false,
		parentFirst = false,
	})
	return getFormattedStatements(args)
end

function p.getCount(frame)
	local args = getArgs(frame, { frameOnly = true })
	args.limit = nil
	return #p.getStatements(args)
end

function p.getRawValue(frame)
	return getRawValue(getArgs(frame, { frameOnly = true }))
end

function p.getQualifier(frame)
	local args = getArgs(frame, { frameOnly = true })
	args.limit = tonumber(args['qualifiers limit'] or args.limit)
	local add_more = prepareShowMore(args)
	local limit = args.limit
	args['qualifiers limit'] = limit
	args.limit = 1
	local qualifiers = getQualifiers(args)
	if #qualifiers == 0 then
		return nil
	end

	add_more = handleShowMore(qualifiers, limit, add_more)
	local Formatters = require 'Modul:Wikidata/Formatters'
	local formattedQualifiers = {}
	for _, qualifier in ipairs(qualifiers) do
		table.insert(formattedQualifiers, Formatters.getFormattedValue(qualifier, args))
	end

	local link = '' -- TODO: we don't have statement anchor
	-- TODO: references?
	return makeList(formattedQualifiers, args, add_more, link)
end

function p.getRawQualifier(frame)
	local args = getArgs(frame, { frameOnly = true })
	args.limit = 1
	for _, qualifier in ipairs(getQualifiers(args)) do
		local Formatters = require 'Modul:Wikidata/Formatters'
		return Formatters.getRawValue(qualifier, args)
	end
	return nil
end

function p.getCurrentId()
	return mw.wikibase.getEntityIdForCurrentPage()
end

function p.formatEntity(frame)
	local args = getArgs(frame, { frameOnly = true })
	args.id = args.id or p.getCurrentId()
	if args.id then
		local Formatters = require 'Modul:Wikidata/Formatters'
		return Formatters.formatRawValue(args.id, 'wikibase-entityid', args)
	end
	return nil
end

function p.entityExists(frame)
	return outputBool(
		mw.wikibase.entityExists(frame.args.id or frame.args[1]),
		lib.IsOptionTrue(frame.args, 'ifexpr'))
end

function p.isValidEntityId(frame)
	return outputBool(
		mw.wikibase.isValidEntityId(frame.args.id or frame.args[1]),
		lib.IsOptionTrue(frame.args, 'ifexpr'))
end

----- API pro moduly -----

function p.formatStatementsFromLua(options)
	return getFormattedStatements(options)
end

function p.getSitelinkFromLua(options)
	return getSitelink(options or {})
end

function p.getStatements(args)
	local id = findEntityId(args)
	return getStatements(id, args)
end

function p.getStatementsWithData(args)
	local statements = p.getStatements(args)
	local result = {}
	for _, statement in ipairs(statements) do
		table.insert(result, formatStatementAndData(statement, args))
	end
	return result
end

function p.getRawValueFromLua(options)
	return getRawValue(options)
end

function p.getRawValues(options)
	local Values = {}
	local Formatters = require 'Modul:Wikidata/Formatters'
	for _, st in ipairs(p.getStatements(options)) do
		table.insert(Values, Formatters.getRawValue(st.mainsnak, options))
	end
	return Values
end

p.formatStatementsTable = formatStatements

function p._compareStatements(args)
	if not args.value then
		error(lib.formatError('param-not-provided', 'value'))
	end
	local statements = p.getStatements(args)
	local compare = require 'Modul:Wikidata/compare'
	return compare.compareValues(args.value, statements, args)
end

return p