Modul:Wikidata
A modult a Modul:Wikidata/doc lapon tudod dokumentálni
require('strict')
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'', ''longitude'' vagy ''both''",
['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, entityId, item)
local result, statements, visited = {}, {}, {[item and item.id or entityId] = true}
local function getStatements(entityId, item)
local wb_statements
if item then
wb_statements = item:getBestStatements(property)
elseif entityId then
wb_statements = mw.wikibase.getBestStatements(entityId, property)
else
return
end
for _, s in ipairs(wb_statements) 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(nil, item)
end
end
end
end
end
getStatements(entityId, 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
local isQualified = false
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 startDate or endDate then
isQualified = true
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
if isQualified then
return result
else
return statements
end
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 getChrDates(chrDate, entityId)
if not chrDate then
return {}
end
if chrDate:match('^P%d+$') then
local dates = mw.wikibase.getEntity(entityId):getBestStatements(chrDate)
local ret = {}
for _, v in ipairs(dates) do
if v.mainsnak.snaktype == 'value' then
table.insert(ret, v.mainsnak.datavalue.value.time)
end
end
return ret
else
return { chrDate }
end
end
local function getDatedStatement(dates, options, dateFields, item)
if not dateFields then
dateFields = { 'atDate' }
end
local result, conflict = nil, false
for _, v in ipairs(dates) do
for _, w in ipairs(dateFields) do
options[w] = v
end
local statement = p.formatStatements(nil, options, item)
if statement == '' then
statement = nil
end
if statement and result == nil then
result = statement
elseif statement ~= result then
conflict = true
end
end
if not conflict then
return result
else
return nil
end
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(nil, options2)
if label2 and label2 ~= '' then
label = label2
end
end
if options.chrProperty and options.chrDate then
local dates = getChrDates(options.chrDate, options.entityId)
local chrLabel = getDatedStatement(dates, {
property = options.chrProperty,
entityId = entityId,
rank = 'valid',
lang = options.lang or 'hu',
firstAfter = true,
['felsorolás'] = nil -- felsorolásjel nélkül
})
if chrLabel then
label = chrLabel
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)
elseif options.format == 'date-object' then
return time
end
return time:formatDate(options)
else
formatError('invalid-value')
end
end
end
local function countryOf(itemId, options, noselflink, chrDate)
local function getStatement(dates, new_options, item)
return getDatedStatement(dates, new_options, { 'atDate', 'chrDate' }, item) or p.formatStatements(nil, new_options, item)
end
if not itemId then
return nil
end
local item = mw.wikibase.getEntity(itemId)
if not item then
return nil
end
local dates = getChrDates(chrDate, options.entityId)
local dateFields = { 'atDate', 'chrDate' }
local new_options = {
property = 'P17',
chrProperty = options.chrProperty,
format = 'raw'
}
if noselflink and item.id == getStatement(dates, new_options, item) then
return nil
end
new_options.format = nil
return getStatement(dates, new_options, 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, options, true, options.chrDate)
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
elseif options.direction == 'both' then
return require('Modul:Coordinate').coord{
datavalue.value.latitude, datavalue.value.longitude,
precision = 'wikidata', format = 'dms'
}
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() or unitId)
else
result = formatNum(amount) .. ' ' .. (unitItem:getLabel() or unitId)
end
else
formatError('unknown-unit', unitId or 'nil')
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)
elseif 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', ( string.gsub( 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)
else
return formatDatavalue(snak.datavalue, options)
end
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 stated_id
local function formatProperty(prop, prop2, dashSeparated, extraOptions)
local localOptions = extraOptions or {}
if dashSeparated then
localOptions['felsorolás'] = nil
localOptions.separator = ' – '
localOptions.conjunction = ' – '
else
localOptions['felsorolás'] = 'szöveg'
end
local formatted = reference.snaks[prop] and formatSnaks(reference.snaks[prop], localOptions)
if formatted and formatted ~= '' then
return formatted
end
if prop2 then
formatted = reference.snaks[prop2] and formatSnaks(reference.snaks[prop2], localOptions)
if formatted and formatted ~= '' then
return formatted
end
end
if stated_id then
localOptions.entityId = stated_id
localOptions.property = prop
formatted = p.formatStatements(localOptions)
if formatted and formatted ~= '' then
return formatted
end
if prop2 then
localOptions.property = prop2
return p.formatStatements(localOptions)
end
end
return nil
end
local args = {}
local url_source = 'reference'
args.url = reference.snaks['P854'] and formatSnak(reference.snaks['P854'][1], options)
if 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
stated_id = formatSnak(reference.snaks.P248[1], {format = 'raw'})
if not args.title then
args.title = p.formatStatements{
entityId = stated_id,
property = 'P1476',
first = true
}
end
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 = stated_id,
property = 'P1687',
first = true,
format = 'raw'
}
if not id_property then
local parts = p.formatStatements{
entityId = stated_id,
property = 'P527',
['felsorolás'] = 'table',
format = 'raw'
}
for _, v in ipairs(parts) do
id_property = p.formatStatements{
entityId = v,
property = 'P1687',
first = true,
format = 'raw'
}
if id_property then
break
end
end
end
if id_property then
url_source = 'external_id'
local id = reference.snaks[id_property]
local fs_options = {first = true, formatExternal = true, formatExternalPlainUrl = true}
if id then
args.url = formatSnak(id[1], fs_options)
else
fs_options.property = id_property
-- call p.formatStatements() as local formatStatements() is not defined yet
args.url = p.formatStatements(nil, fs_options, entity)
end
end
end
if not args.url then
url_source = 'stated_in'
args.url = p.formatStatements{
entityId = stated_id,
property = 'P953',
first = true
}
end
end
if args.url and args.title then -- url and title
local Time = {}
if reference.snaks.P577 or reference.snaks.P813 or (reference.snaks.P1065 and reference.snaks.P2960) then
Time = require('Modul:Time')
end
if url_source ~= 'external_id' then
args.author = formatProperty('P50', 'P2093', true)
end
local time
if reference.snaks.P577 then
time = Time.newFromWikidataValue(reference.snaks.P577[1].datavalue.value)
elseif stated_id then
time = p.formatStatements{
entityId = stated_id,
property = 'P577',
first = true,
format = 'date-object'
}
end
if time then
if time.precision >= 11 then
args.date = time:toIso8601()
else
args.year = tostring(time.year)
end
end
if url_source ~= 'external_id' then
args.publisher = formatProperty('P123', nil, true)
end
args.language = formatProperty('P407', 'P364', false, {link = 'nem'})
args.accessdate = reference.snaks['P813'] and Time.newFromWikidataValue(reference.snaks.P813[1].datavalue.value):toIso8601()
if args.url and args.url:match('^https?://www.ksh.hu') then
args.url = args.url:gsub('p_lang=EN', 'p_lang=HU')
end
if reference.snaks.P1065 and reference.snaks.P2960 then
args.archiveurl = formatSnak(reference.snaks.P1065[1], options)
args.archivedate = Time.newFromWikidataValue(reference.snaks.P2960[1].datavalue.value):toIso8601()
end
return frame:expandTemplate{title = 'Cite web', args = args}
else
local result = {}
local excluded = true
options.formatExternal = true
for key, referenceSnaks in pairs(reference.snaks) do
-- exclude "imported from Wikimedia project", "Wikimedia import URL" and "inferred from"
if key ~= 'P143' and key ~= 'P4656' and key ~= 'P3452' then
-- don't show references with nothing more than an access date
if key ~= 'P813' then
excluded = false
end
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
if excluded then
return ''
else
return table.concat(result, ', ')
end
end
end
local function formatReferences(references, options, entity)
if not references then
return ''
end
if not entity and options.entityId then
entity = mw.wikibase.getEntity(options.entityId)
end
local formattedReferences = {}
for _, reference in ipairs(references) do
local formattedReference = formatReference(reference, options, entity)
if formattedReference and formattedReference ~= '' then
table.insert(formattedReferences, frame:extensionTag('ref', formattedReference, {name = reference.hash}))
end
end
return table.concat(formattedReferences)
end
local function populationWithPointInTime(statement, options, entity, last)
if statement.mainsnak.snaktype ~= 'value' then
return nil
end
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
if last and options.punctuation then
text = text .. options.punctuation
end
text = text .. formatReferences(statement.references, options, entity)
if last then
text = text .. string.format(' <small class="plainlinks noexcerpts">[https://www.wikidata.org/wiki/%s?uselang=hu#P1082 +/-]</small>', entity and entity:getId() or options.entityId)
end
return text
end
local function sortAuxiliary(statements, propGenerator)
local newlist, auxlist = {}, {}
local function sort(a, b)
if a.prop and b.prop and a.prop ~= b.prop then
return a.prop < b.prop
elseif a.prop and b.prop then
return a.i < b.i
elseif a.prop or b.prop then
return not a.prop
else
return a.i < b.i
end
end
for i, v in ipairs(statements) do
auxlist[i] = {
i = i,
prop = propGenerator(v, i)
}
end
table.sort(auxlist, sort)
for _, v in ipairs(auxlist) do
table.insert(newlist, statements[v.i])
end
return newlist
end
local function getSortableValue(snak)
if not snak or snak.snaktype ~= 'value' then
return nil
end
local datavalue = snak.datavalue
if datavalue.type == 'wikibase-entityid' then
local id = 'Q' .. 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)
elseif datavalue.type == 'string' then
return datavalue.value
elseif datavalue.type == 'time' then
return require('Modul:Time').newFromWikidataValue(datavalue.value)
elseif datavalue.type == 'quantity' then
return tonumber(datavalue.value.amount)
elseif datavalue.type == 'monolingualtext' then
return datavalue.value.text
end
return nil
end
local function sortByValue(statements)
local function propGenerator(v)
return getSortableValue(v.mainsnak)
end
return sortAuxiliary(statements, propGenerator)
end
local function sortByQualifier(statements, qualifier)
local function propGenerator(v)
return v.qualifiers and v.qualifiers[qualifier] and getSortableValue(v.qualifiers[qualifier][1])
end
return sortAuxiliary(statements, propGenerator)
end
local function formatStatements(options, item)
if not options.property or options.property == '' then
formatError('property-param-not-provided')
end
local property = options.property:upper()
--Get entity
local entity = item
local statements
if entity then
statements = entity:getAllStatements(property)
else
if not options.entityId or options.entityId == '' then
options.entityId = mw.wikibase.getEntityIdForCurrentPage()
end
if not options.entityId then
return options['felsorolás'] == 'table' and {} or nil
end
statements = mw.wikibase.getAllStatements(options.entityId, property)
end
if #statements == 0 then
return options['felsorolás'] == 'table' and {} or nil
end
if options.atDate then
statements = atDate(statements, options.atDate)
end
-- 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, options.entityId, entity)
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.sort then
local comp = options.sort
if type(comp) == 'string' and comp:match('[Pp]%d+') then
statements = sortByQualifier(statements, string.upper(comp))
elseif comp == '' or comp == true then
statements = sortByValue(statements)
else
table.sort(statements, comp)
end
end
if options.first then
statements = firstValue(statements)
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, entity, (i == #statements))
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['felsorolás'] == 'table' then
return formattedStatements
elseif options.separator or options.conjunction then
options.separator = options.separator and string.gsub(options.separator, ' ', ' ')
options.conjunction = options.conjunction and string.gsub(options.conjunction, ' ', ' ')
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
local dash = '–'
if (startDate and not startDate:match('^%d+$')) or (endDate and not endDate:match('^%d+$')) then
dash = ' – '
end
return (startDate or '') .. dash .. (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', direction = 'both', showUnit = true})
if qualifiers then
-- order determined by the order in parameter
if orderedResult[key] then
table.insert(orderedResult[key], formattedSnak)
else
orderedResult[key] = { formattedSnak }
end
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
for _, v in ipairs(orderedResult[qualifier]) do
table.insert(result, v)
end
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 then
result = result .. formatReferences(statement.references, options, entity)
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)
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
if args.rank == 'all' then
return true
elseif args.rank == 'valid' then
-- if we're just searching, it doesn't matter
-- if we want all or only the better ones
args.rank = nil
end
for _, claim in pairs(entity.claims[args.property:upper()]) do
if args.rank and claim.rank == args.rank or not args.rank and claim.rank ~= 'deprecated' then
return true
end
end
return nil
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