Ez a lap műszaki védett

Modul:Wikidata

A Wikipédiából, a szabad enciklopédiából

Source code project 1171.svg Wikidata[mi ez?] • [dokumentáció: mutat, szerkeszt] • [tesztek: success: 4, error: 1, skipped: 0 (részletek)]

Wikidata-adatok formázott megjelenítése, a {{Wikidata}} sablon implementációja.

Wikikódból hívható függvények

formatStatements

Paraméterek

property 
A Wikidatában tárolt tulajdonság azonosítója. Például p856.
value 
A Wikidatában tárolt érték helyett megjelenítendő érték.
direction 
Koordináták dimenziója. Értéke latitude és longitude lehet.
link 
Értéke nem, ha azt szeretnénk, hogy a függvény értéke ne link legyen, hanem csak a címke; csak, ha pedig azt szeretnénk, hogy csak a kapcsolt Wikipédia-szócikk.
lang
A címke nyelvének megadása, több nyelv esetén vesszővel elválasztva, szóköz nélkül, ekkor az első olyan nyelven jeleníti meg a címkét, amin létezik. Alapértelmezetten hu,en.
first 
Ha azt szeretnénk, hogy csak egy értéket adjon vissza, például képeknél.
showQualifiers
Összes minősítő megjelenítése, vagy megadott minősítők megjelenítése (ha a paraméterérték tulajdonságazonosítók listája, pl. P580, P582).
showReferences
Forráshivatkozások megjelenítése
rank 
Értékei: preferred, normal, deprecated, all, valid. Ha nincs megadva, akkor a legmagasabb rangúakat adja vissza. A valid a preferred és a normal együttesen.
életkor 
Értéke igen.
felsorolás 
Értékei: lista, számozott lista, sorok, szöveg. Ha nincs megadva, akkor sorok az alapértelmezett.
format 
raw, tárolt érték formázás nélkül
default, népesség formázása a Népesség-sablon alapmegjelenítése szerint
iso, dátum ISO 8601 formátumban
sort 
Rendezés több érték estén.
formatExternal
Külső azonosító típusú tulajdonság esetén visszatérés egy linkkel (szövege az azonosító)
formatExternalPlainUrl
A fenti paraméter használata esetén linkszöveg mellőzése, visszatérés csupasz URL-lel
dateformat
Dátumformátum a {{#time:}} értelmezőfüggvénynek (csak a népesség dátumánál működik, más helyzetben a változó pontosság – napra pontostól az évmilliárdig bármi lehet – és a függvény behatároltsága – csak 111-től 9999-ig értelmezi az éveket – miatt nincs értelme megadni egy fix formátumot).
punctuation
Központozás az utolsó érték és esetleges minősítői után, de a hozzá tartozó forráshivatkozás előtt. Általában felsorolás=lista esetén van értelme.

containsProperty

Wikidata-tulajdonság meglétének vizsgálata. Lásd {{Wikidata-f}}.

Luából hívható függvények

containsPropertyWithValue

Tulajdonág értékének vizsgálata.

withHighestRank

Tulajdonság értékeinek szűrése a legmagasabb fokozattal (rank) rendelkező értékekre.

formatStatement

Tulajdonság egy értékének formázott megjelenítése.

Használt modulok, sablonok

  • Modul:Arguments – paraméterek beolvasásához
  • Modul:Time – dátum kiírásához (formázottan)
  • {{plainlist}}(?) – alapértelmezett kimenetnél a többelemű listák formázásához
require('Modul:No globals')

local p = {}

local getArgs = require('Modul:Arguments').getArgs
local frame = mw.getCurrentFrame()

local i18n = {
	['errors'] = {
		['property-param-not-provided'] = "Hiányzó ''property='' paraméter",
		['entity-not-found'] = 'Nem létező Wikidata-elem',
		['unknown-claim-type'] = 'Ismeretlen az állítás típusa',
		['unknown-snak-type'] = 'Ismeretlen a snak típusa',
		['unknown-datavalue-type'] = 'Ismeretlen az érték típusa',
		['unknown-entity-type'] = 'Ismeretlen a Wikidata-elem típusa',
		['unknown-value-module'] = "A ''value-module'' és ''value-function'' paramétert egyszerre kell beállítani",
		['value-module-not-found'] = "A ''value-module'' nem létező modulra mutat",
		['value-function-not-found'] = "A ''value-function'' nem létező funkcióra mutat",
		['globecoordinate-direction'] = "Az érték típusa ''globecoordinate'' : kell ''direction=latitude'' vagy ''longitude''",
		['invalid-value'] = 'Érvénytelen érték',
		['unknown-unit'] = 'Ismeretlen mértékegység: %s',
	},
	['somevalue'] = "''nem ismert''",
	['novalue'] = "''nincs''"
}

local function formatError(key, ...)
	error(i18n.errors[key]:format(...), 2)
end

local function getUpperLevelOfType(property, typeId, item)
	local result, statements, visited = {}, {}, {[item.id] = true}
	local function getStatements(item)
		if not item or not item.claims or not item.claims[property] then
			return
		end
		for _, s in ipairs(item:getBestStatements(property)) do
			if s.mainsnak.snaktype == 'value' then
				local itemId = 'Q' .. s.mainsnak.datavalue.value['numeric-id']
				if not visited[itemId] then
					visited[itemId] = true
					local item = mw.wikibase.getEntity(itemId)
					if p.containsPropertyWithValue(item, 'P31', typeId) then
						statements[item.id] = s
					else
						getStatements(item)
					end
				end
			end
		end
	end
	getStatements(item)
	for _, s in pairs(statements) do
		table.insert(result, s)
	end
	return result
end

local function firstValue(statements)
	for _, statement in ipairs(statements) do
		if statement.rank == 'preferred' then
			return {statement}
		end
	end
	for _, statement in ipairs(statements) do
		if statement.rank == 'normal' then
			return {statement}
		end
	end
	return {}
end

local function withRank(statements, ranks)
	local result = {}
	for _i, statement in ipairs(statements) do
		for _j, rank in ipairs(ranks) do
			if statement.rank == rank then
				table.insert(result, statement)
				break
			end
		end
	end
	return result
end

function p.withHighestRank(statements)
	local preferred, normal = {}, {}
	for _, statement in ipairs(statements) do
		if statement.rank == 'preferred' then
			table.insert(preferred, statement)
		elseif statement.rank == 'normal' then
			table.insert(normal, statement)
		end
	end
	return #preferred > 0 and preferred or normal
end

local function atDate(statements, date)
	local result = {}
	local Time = require('Modul:Time')
	local time = Time.newFromIso8601(date, true)
	if not time then
		return statements
	end
	for _, s in ipairs(statements) do
		local startDate, endDate
		if s.qualifiers and s.qualifiers.P580 and #s.qualifiers.P580 == 1 and s.qualifiers.P580[1].snaktype == 'value' then
			startDate = Time.newFromWikidataValue(s.qualifiers.P580[1].datavalue.value)
		end
		if s.qualifiers and s.qualifiers.P582 and #s.qualifiers.P582 == 1 and s.qualifiers.P582[1].snaktype == 'value' then
			endDate = Time.newFromWikidataValue(s.qualifiers.P582[1].datavalue.value)
		end
		if not startDate and endDate and time <= endDate or
			startDate and not endDate and startDate <= time or
			startDate and endDate and startDate <= time and time <= endDate then
			table.insert(result, s)
		end
	end
	return result
end

local function getEntityFromId(id)
	if id and id ~= '' then
		return mw.wikibase.getEntity(id)
	end
	return mw.wikibase.getEntity()
end

local function getEntityIdFromValue(value)
	local prefix
	if value['entity-type'] == 'item' then
		prefix = 'Q'
	elseif value['entity-type'] == 'property' then
		prefix = 'P'
	else
		formatError('unknown-entity-type')
	end
	return prefix .. value['numeric-id']
end

local function populationWithPointInTime(statement, options)
	local population = tonumber(statement.mainsnak.datavalue.value.amount)
	local text = (population < 10000 and tostring(population) or mw.getContentLanguage():formatNum(population)) .. ' fő'

	if statement.qualifiers and statement.qualifiers.P585 then  -- dátum
		local time, fDate = require('Modul:Time').newFromWikidataValue(statement.qualifiers.P585[1].datavalue.value)
		if time.precision >= 11 then
			fDate = mw.getContentLanguage():formatDate(options.dateformat or 'Y. M. j.', time:toIso8601())
		else
			fDate = tostring(time.year)
		end
		text = text .. ' ' .. mw.text.tag('span', {style = 'font-size:90%; white-space:nowrap;'}, '(' .. fDate .. ')')
	end
	return text
end

local function formatEntityId(entityId, options)
	local link = mw.wikibase.sitelink(entityId)
	if options.link == 'csak' then
		return link
	end
	if link and options.link ~= 'nem' and mw.ustring.sub(link, 1, 10) == 'Kategória:' then
		return '[[' .. link .. ']]'
	end
	local label
	if options.lang then
		for lang in mw.text.gsplit(options.lang, ',') do
			label = mw.wikibase.getLabelByLang(entityId, lang)
			if label then
				break
			end
		end
	else
		label = mw.wikibase.label(entityId)
	end
	if options.labelProperty then
		local options2 = {}
		for k, v in pairs(options) do
			if k ~= 'labelProperty' then
				options2[k] = v
			end
		end
		options2.property = options.labelProperty
		options2.entityId = entityId
		options2.rank = 'valid'
		options2.link = 'nem'
		options2.lang = options.lang or 'hu'
		options2.firstAfter = true
		options2['felsorolás'] = nil -- felsorolásjel nélkül
		local label2 = p.formatStatements(frame, options2)
		if label2 and label2 ~= '' then
			label = label2
		end
	end
	if options.chrProperty and options.chrDate then
		local time
		if options.chrDate:match('^P%d+$') then
			local dates = mw.wikibase.getEntity(options.entityId):getBestStatements(options.chrDate)
			if #dates == 1 and dates[1].mainsnak.snaktype == 'value' then
				time = dates[1].mainsnak.datavalue.value.time
			end
		else
			time = options.chrDate
		end
		if time then
			local chrLabel = p.formatStatements(frame, {
				property = options.chrProperty,
				entityId = entityId,
				atDate = time,
				rank = 'valid',
				lang = options.lang or 'hu',
				firstAfter = true,
				['felsorolás'] = nil -- felsorolásjel nélkül
			})
			if chrLabel and chrLabel ~= '' then
				label = chrLabel
			end
		end
	end
	if label and options.format == 'ucfirst' then
		label = mw.language.getContentLanguage():ucfirst(label)
	end
	if link and options.link ~= 'nem' then
		if label then
			if mw.ustring.sub(label, 2) == mw.ustring.sub(link, 2) and 
				mw.ustring.lower(mw.ustring.sub(label, 1, 1)) == mw.ustring.lower(mw.ustring.sub(link, 1, 1)) then
				return '[[' .. label .. ']]'
			else
				return '[[' .. link .. '|' .. label .. ']]'
			end
		else
			return '[[' .. link .. ']]'
		end
	else
		return label or link  --TODO what if no links and label + fallback language?
	end
end

local function formatTimeValue(value, options)
	if options.format == 'raw' then
		return value.time
	else
		local time = require('Modul:Time').newFromWikidataValue(value)
		if time then
			if options.format == 'iso' then
				return tostring(time)
			end
			return time:formatDate(options)
		else
			formatError('invalid-value')
		end
	end
end

local function countryOf(itemId, noselflink)
	if not itemId then
		return nil
	end
	local item = mw.wikibase.getEntity(itemId)
	if not item then
		return nil
	end
	if noselflink and item.id == p.formatStatements(frame, {property = 'P17', format = 'raw'}, item) then
		return nil
	end
	return p.formatStatements(frame, {property = 'P17'}, item)
end

local function formatNum(amount)
	if amount < 10000 and -10000 < amount then
		return tostring(amount):gsub('%.', ',')
	else
		return mw.getContentLanguage():formatNum(amount)
	end
end

local function formatDatavalue(datavalue, options)
	--Use the customize handler if provided
	if options['value-module'] or options['value-function'] then
		if not options['value-module'] or not options['value-function'] then
			return formatError( 'unknown-value-module' )
		end
		local formatter = require ('Module:' .. options['value-module'])
		if formatter == nil then
			return formatError( 'value-module-not-found' )
		end
		local fun = formatter[options['value-function']]
		if fun == nil then
			return formatError( 'value-function-not-found' )
		end
		return fun( datavalue.value, options )
	end

	--Default formatters
	if datavalue.type == 'wikibase-entityid' then
		local itemId = getEntityIdFromValue(datavalue.value)
		if options.format == 'raw' then
			return itemId
		end
		local result = formatEntityId(itemId, options)
		if not result then
			return nil
		end
		local country = options.format == 'with_country' and countryOf(itemId, true, options)
		return result .. (country and ', ' .. country or '')
	elseif datavalue.type == 'string' then
		return datavalue.value --TODO ids + media
	elseif datavalue.type == 'time' then
		return formatTimeValue(datavalue.value, options)
	elseif datavalue.type == 'globecoordinate' then
		if options.direction == 'latitude' then
			return datavalue.value.latitude
		elseif options.direction == 'longitude' then
			return datavalue.value.longitude
		else
			return formatError('globecoordinate-direction')
		end
	elseif datavalue.type == 'quantity' then
		if options.format == 'raw' then
			return datavalue.value.amount
		end
		local result
		local amount = tonumber(datavalue.value.amount)
		if datavalue.value.unit == '1' then
			if options.unit then
				return nil
			end
			result = formatNum(amount)
		else
			local unitId = datavalue.value.unit:match('Q%d+')
			local sourceUnit = mw.loadData('Modul:Wikidata/units').wikidata_item_ids[unitId]
			if not sourceUnit then
				if not options.unit then
					local unitItem = mw.wikibase.getEntity(unitId)
					if p.isOfType(unitItem, 'Q8142') then  -- currency
						local symbol = unitItem:getBestStatements('P558')[1]
						result = formatNum(amount) .. ' ' .. (symbol and p.formatStatement(symbol) or unitItem:getLabel())
					else
						result = formatNum(amount) .. ' ' .. unitItem:getLabel()
					end
				else
					formatError('unknown-unit', unitId)
				end
			else
				local targetUnit = options.unit or sourceUnit
				result = require('Modul:Convert')._convert{amount, sourceUnit, targetUnit, disp = options.showUnit and 'out' or 'number'}
			end
		end
		return result
	elseif datavalue.type == 'monolingualtext' then
		if not options.lang or options.lang == '~hu' and datavalue.value.language ~= 'hu' then
			return datavalue.value.text
		end
		for lang in mw.text.gsplit(options.lang, ',') do
			if lang:match('^%s*(.-)%s*$') == datavalue.value.language then
				return datavalue.value.text
			end
		end
		return nil
	else
		formatError('unknown-datavalue-type')
	end
end

local function formatSnak(snak, options)
	local options = options or {}
	if snak.snaktype == 'somevalue' then
		return options.somevalue or i18n['somevalue']
	elseif snak.snaktype == 'novalue' then
		return i18n['novalue']
	elseif snak.snaktype == 'value' then
		if options['value-module'] or options['value-function'] then
			return formatDatavalue(snak.datavalue, options)
		end
		if snak.datatype == 'math' then
			return frame:extensionTag('math', snak.datavalue.value)
		end
		if snak.datatype == 'external-id' then
			if options['formatExternal'] then
				local formatter = p.formatStatements{
					entityId = snak.property,
					property = 'P1630',
					first = true
				}
				if formatter and formatter ~= '' then
					local id = formatDatavalue(snak.datavalue, options)
					local url = string.gsub( formatter, '%$1', id )
					if options['formatExternalPlainUrl'] then
						return url
					else
						return string.format( '[%s %s]', url, id )
					end
				end
				-- else fall back to plain version
			end
			return formatDatavalue(snak.datavalue, options)
		end
		return formatDatavalue(snak.datavalue, options)
	else
		formatError('unknown-snak-type')
	end
end

local function formatSnaks(snaks, options)
	local formattedSnaks = {}
	for _, snak in ipairs(snaks) do
		table.insert(formattedSnaks, formatSnak(snak, options))
	end
	return mw.text.listToText(formattedSnaks, options.separator, options.conjunction)
end

local function formatReference(reference, options, entity)
	local args = {}
	args.url = reference.snaks['P854'] and formatSnak(reference.snaks['P854'][1], options)
	args.title = reference.snaks['P357'] and formatSnak(reference.snaks['P357'][1], options)
	if not args.title and reference.snaks.P1476 then
		for _, snak in ipairs(reference.snaks.P1476) do
			if not args.title or (snak.datavalue and snak.datavalue.value.language == 'hu') then
				args.title = snak.datavalue.value.text
			end
		end
	end
	if reference.snaks.P248 and type(entity) == 'table' then
		if not args.title then
			args.title = formatSnaks(reference.snaks.P248, {link = 'nem'})
		end
		if not args.url then
			local id_property = p.formatStatements{
				entityId = formatSnak(reference.snaks.P248[1], {format = 'raw'}),
				property = 'P1687',
				first = true,
				format = 'raw'
			}
			if id_property then
			-- call p.formatStatements() as local formatStatements() is not defined yet
				args.url = p.formatStatements(nil, {property = id_property, formatExternal = true, formatExternalPlainUrl = true}, entity)
			end
		end
	end
	if args.url and args.title then  -- url and title
		local Time = {}
		if reference.snaks.P577 or reference.snaks.P813 then
			Time = require('Modul:Time')
		end

		args.author = reference.snaks['P50'] and formatSnak(reference.snaks['P50'][1], options)
		if reference.snaks.P577 then
			local time = Time.newFromWikidataValue(reference.snaks.P577[1].datavalue.value)
			if time.precision >= 11 then
				args.date = time:toIso8601()
			else
				args.year = tostring(time.year)
			end
		end
		args.publisher = reference.snaks['P123'] and formatSnak(reference.snaks['P123'][1], options)
		args.language = reference.snaks['P407'] and formatSnaks(reference.snaks['P407'], {link = 'nem'})
		if not args.language then
			args.language = reference.snaks['P364'] and formatSnaks(reference.snaks['P364'], {link = 'nem'})
		end
		args.accessdate = reference.snaks['P813'] and Time.newFromWikidataValue(reference.snaks.P813[1].datavalue.value):toIso8601()

		if args.url and args.url:sub(1, 17) == 'http://www.ksh.hu' then
			args.url = args.url:gsub('p_lang=EN', 'p_lang=HU')
		end

		return frame:expandTemplate{title = 'Cite web', args = args}
	else
		local result = {}
		options.formatExternal = true
		for key, referenceSnaks in pairs(reference.snaks) do
			if key ~= 'P143' then  -- imported from
				for _, snak in ipairs(referenceSnaks) do
					table.insert(result, formatSnak(snak, snak.datavalue and snak.datavalue.type == 'time' and {link = 'nem'} or options))
				end
			end
		end
		return table.concat(result, ', ')
	end
end

local function formatStatements(options, item)
	if not options.property then
		formatError('property-param-not-provided')
	end
	local property = options.property:upper()
	--Get entity
	local entity = item
	if not entity then
		entity = getEntityFromId(options.entityId ~= '' and options.entityId or nil)
	end
	if not entity then
		return nil
	end
	if not entity.claims or not entity.claims[property] then
		return nil  --TODO error?
	end
	local statements = entity.claims[property]

	-- TODO Extract selection and filtering
	if options.rank ~= 'all' then
		if not options.rank then
			statements = p.withHighestRank(statements)
		elseif options.rank == 'valid' then
			statements = withRank(statements, {'normal', 'preferred'})
		else
			statements = withRank(statements, {options.rank})
		end
	end

	if options.typeId then
		statements = getUpperLevelOfType(property, options.typeId, entity)
	end

	if options.atDate then
		statements = atDate(statements, options.atDate)
	end

	if options.excludespecial then
		local newStatements = {}
		for _, s in ipairs(statements) do
			if s.mainsnak.snaktype == 'value' then
				table.insert(newStatements, s)
			end
		end
		statements = newStatements
	end

	if options.first then
		statements = firstValue(statements)
	end

	-- TODO Extract sorting
	if options.sort then
		local comp = options.sort
		if comp == '' then
			comp = function (s1, s2)
				if s1.mainsnak.snaktype ~= 'value' or s2.mainsnak.snaktype ~= 'value' then
					return nil
				end
				local sortKey
				local type = s1.mainsnak.datavalue.type
				if type == 'wikibase-entityid' then
					sortKey = function(statement)
						local id = 'Q' .. statement.mainsnak.datavalue.value['numeric-id']
						local key = mw.wikibase.label(id)
						if not key then
							key = mw.wikibase.sitelink(id)
						end
						if not key then
							return id
						end
						return mw.language.getContentLanguage():caseFold(key)
					end
				end
				return sortKey(s1) < sortKey(s2)
			end
		end
		table.sort(statements, comp)
	end

	--Format statement and concat them cleanly
	local formattedStatements = {}
	-- loop variable to know if we're processing the last statement
	local i = 0
	for _, statement in ipairs(statements) do
		i = i + 1
		local fs
		if property == 'P1082' and options.format == 'default' then  -- population
			fs = populationWithPointInTime(statement, options) .. ((i == #statements and options.punctuation) or '')
			if statement.references then
				for _, reference in ipairs(statement.references) do
					local formattedReference = formatReference(reference, options, entity)
					if formattedReference and formattedReference ~= '' then
						fs = fs .. frame:extensionTag('ref', formattedReference, {name = reference.hash})
					end
				end
			end
		else
			fs = p.formatStatement(statement, options, entity, (i == #statements))
		end
		if fs then
			if options['felsorolás'] == 'lista' then
				fs = '* ' .. fs
			elseif options['felsorolás'] == 'számozott lista' then
				fs = '# ' .. fs
			end
			table.insert(formattedStatements, fs)
		end
	end

	local function plainlist(items)
		if #items == 0 then
			return ''
		end
		if #items == 1 then
			return items[1]
		end
		return frame:expandTemplate{ title = 'Plainlist', args = { '\n* ' .. table.concat(items, '\n* ') .. '\n' } }
	end

	if options['felsorolás'] == 'lista' or options['felsorolás'] == 'számozott lista' then
		return table.concat(formattedStatements, '\n')
	elseif options['felsorolás'] == 'sorok' then
		return plainlist(formattedStatements)
	elseif options['felsorolás'] == 'szöveg' then
		return mw.text.listToText(formattedStatements)
	elseif options.separator or options.conjunction then
		options.separator = options.separator and string.gsub(options.separator, '&#32;', ' ')
		options.conjunction = options.conjunction and string.gsub(options.conjunction, '&#32;', ' ')
		return mw.text.listToText(formattedStatements, options.separator, options.conjunction)
	else
		if options.firstAfter then
			return formattedStatements[1] or ''
		end
		return plainlist(formattedStatements)
	end
end

local function formatQualifiers(statement, options, qualifiers)
	local result, orderedResult, startDate, endDate = {}, {}
	local function getInterval()
		if startDate and startDate ~= '' or endDate and endDate ~= '' then
			return (startDate or '') .. '–' .. (endDate or '')
		end
	end
	if type(qualifiers) == 'string' and qualifiers:find('[Pp]%d') then
		qualifiers = qualifiers:upper()
	else
		qualifiers = nil
	end
	for key, snaks in pairs(statement.qualifiers) do
		if not qualifiers or qualifiers:find(key, 1, true) then
			if key == 'P580' then
				startDate = formatSnak(snaks[1], {link = 'nem'})
			elseif key == 'P582' then
				endDate = formatSnak(snaks[1], {link = 'nem'})
			else
				for _, snak in ipairs(snaks) do
					local formattedSnak = formatSnak(snak, {link = 'nem'})
					if qualifiers then
						-- order determined by the order in parameter
						orderedResult[key] = formattedSnak
					else
						table.insert(result, formattedSnak)
					end
				end
			end
		end
	end
	if qualifiers then
		for qualifier in qualifiers:gmatch('P%d+') do
			if qualifier == 'P580' or qualifier == 'P582' then
				local interval = getInterval()
				if interval then
					table.insert(result, interval)
					-- prevent interval to be inserted twice (both at P580 and P582)
					startDate, endDate = nil, nil
				end
			elseif orderedResult[qualifier] then
				table.insert(result, orderedResult[qualifier])
			end
		end
	else
		local interval = getInterval()
		if interval then
			table.insert(result, 1, interval)
		end
	end
	return table.concat(result, ', ')
end

function p.formatStatement(statement, options, entity, last)
	if not statement.type or statement.type ~= 'statement' then
		formatError('unknown-claim-type')
	end
	local options = options or {}
	local result
	if statement.mainsnak.snaktype == 'somevalue' and statement.mainsnak.datatype == 'time' and statement.qualifiers and 
		(statement.qualifiers.P1319 or statement.qualifiers.P1326) then
		-- TODO Extract method
		if statement.qualifiers.P1319 then
			if statement.qualifiers.P1326 then
				result = formatSnak(statement.qualifiers.P1319[1]) .. ' és ' .. formatSnak(statement.qualifiers.P1326[1]) .. ' között'
			else
				result = formatSnak(statement.qualifiers.P1319[1]) .. ' után'
			end
		else
			result = formatSnak(statement.qualifiers.P1326[1]) .. ' előtt'
		end
	else
		result = formatSnak(statement.mainsnak, options)
	end

	--TODO reference and qualifiers
	if result and result ~= '' then
		if options.showQualifiers and statement.qualifiers then
			local formattedQualifiers = formatQualifiers(statement, options, options.showQualifiers)
			if formattedQualifiers and formattedQualifiers ~= '' then
				result = result .. ' <small>(' .. formattedQualifiers .. ')</small>'
			end
		end
		if last and options.punctuation then
			result = result .. options.punctuation
		end
		if options.showReferences and statement.references then
			for _, reference in ipairs(statement.references) do
				local formattedReference = formatReference(reference, options, entity)
				if formattedReference and formattedReference ~= '' then
					result = result .. frame:extensionTag('ref', formattedReference, {name = reference.hash})
				end
			end
		end
	end
	return result
end

function p.formatStatements(frame, args, item)
	if not args then
		args = getArgs(frame, { removeBlanks = false })
	end

	--If a value if already set, use it
	if args.value and args.value ~= '' then
		return args.value ~= '-' and args.value or nil
	end
	return formatStatements(args, item)
end

--[[
	Returns string true if connected Wikibase item contains property specified 
	by property argument, empty string otherwise.
	Used by template Wikidata-f in conditional expressions.
--]]
function p.containsProperty(frame, args, item)
	if not args then
		args = getArgs(frame, {frameOnly = true, readOnly = true})
	end
	if args.value == '-' then
		return nil
	end
	if args.value then
		return 'true'
	end
	if not args.property then
		formatError('property-param-not-provided')
	end
	local entity = item or mw.wikibase.getEntity(args.entityId ~= '' and args.entityId or nil)
	if not entity or not entity.claims or not entity.claims[args.property:upper()] then
		return nil
	end
	return 'true'
end

function p.containsPropertyWithValue(item, property, value)
	if not property or not value then
		return false
	end
	if not item or not item.claims or not item.claims[property:upper()] then
		return false
	end
	for _, statement in ipairs(item.claims[property:upper()]) do
		if statement.rank ~= 'deprecated' and statement.mainsnak.snaktype == 'value' then
			local type = statement.mainsnak.datavalue.type
			if type == 'wikibase-entityid' then
				if 'Q' .. statement.mainsnak.datavalue.value['numeric-id'] == value then
					return true
				end
			end
		end
	end
	return false
end

function p.isOfType(item, class)
	if not item or not item.claims or not item.claims.P31 or not class then
		return false
	end
	local isSubclass, visited

	local function checkProperty(item, property)
		for _, s in ipairs(item:getBestStatements(property)) do
			if s.mainsnak.snaktype == 'value' then
				local itemId = 'Q' .. s.mainsnak.datavalue.value['numeric-id']
				if itemId == class or isSubclass(itemId) then
					return true
				end
			end
		end
		return false
	end

	isSubclass = function (itemId)
		if visited[itemId] then
			return false
		end
		local item = mw.wikibase.getEntity(itemId)
		if not item then  -- deleted item
			return false
		end
		visited[itemId] = true
		visited[item.id] = true
		return checkProperty(item, 'P279')
	end

	visited = { [item.id] = true }
	return checkProperty(item, 'P31')
end

return p