Modulo:Wikidata: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
aggiunto rank "best"
m inverto logica del parametro per retrocompatibilità
 
(117 versioni intermedie di 7 utenti non mostrate)
Riga 1:
--[[
* Modulo per implementare le funzionalità dei template:
* Modulo per accedere a Wikidata in modo più avanzato rispetto a {{#property}}.
* {{Wikidata}}, {{WikidataQ}}, {{WikidataIdx}}, {{WikidataN}}, {{WikidataLabel}}, {{WikidataDescription}}
* {{WikidataLink}}, {{WikidataId}}, {{WikidataTipo}} e {{WikidataIstanza}}.
* Permette di accedere a Wikidata in modo più avanzato rispetto a {{#property}}.
 
* Per la maggior parte riscritto e ampliato a partire dalla versione iniziale a:
* Il modulo è stato importato inizialmente da:
* http://test2.wikipedia.org/w/index.php?title=Module:Wikidata&oldid=52322
]]
 
-- =============================================================================
-- Messaggi di errore
-- Non utilizzare mai mw.wikibase.getEntity, per esempio un solo utilizzo di
-- mw.wikibase.getEntity('Q183') fa aumentare di 7 MB l'utilizzo di memoria
-- per Lua ed è molto lenta se ripetuta (unico utilizzo in getDatatype,
-- solo per proprietà, non essendoci alternative).
-- =============================================================================
 
require('strict')
 
local getArgs = require('Module:Arguments').getArgs
local mConvert = require('Module:Conversione')
local mLanguages = require('Module:Lingue')
 
-- Categoria per le pagine con errori
local errorCategory = '[[Categoria:Voci con errori del modulo Wikidata]]'
 
-- Messaggi
local i18n = {
[" errors"] = {
["property'entityid-param-not-provided"'] = "Parametro ''propertyentityid'' non fornito.",
["qualifier'property-param-not-provided"'] = "Parametro ''qualifierproperty'' non fornito.",
["entity'qualifier-param-not-found"provided'] = "EntitàParametro ''qualifier'' non trovata.fornito",
['value-param-not-provided'] = "Parametro ''valore'' da ricercare non fornito",
["unknown-claim-type"] = "Tipo asserzione sconosciuta.",
['entity-not-found'] = 'Entità non trovata',
["unknown-snak-type"] = "Tipo di snak sconosciuto.",
["'unknown-datavalueclaim-type"'] = "'Tipo di datoasserzione sconosciuto."sconosciuta',
["'unknown-entitysnak-type"'] = "'Tipo di entitàsnak sconosciuta."sconosciuto',
['unknown-datavalue-type'] = 'Tipo di dato sconosciuto',
["unknown-value-module"] = "Devi impostare entrambi i parametri: ''value-module'' e ''value-function''.",
['unknown-entity-type'] = 'Tipo di entità sconosciuta',
["value-module-not-found"] = "Modulo indicato da ''value-module'' non trovato.",
['unknown-output-format'] = 'Formato di output sconosciuto'
["value-function-not-found"] = "Funzione indicata da ''value-function'' non trovata."
},
[" somevalue"] = "''valore sconosciuto''",
[" novalue"] = "''nessun valore''",
datatypes = {
['commonsMedia'] = 'file multimediale su Commons',
['external-id'] = 'identificativo esterno',
['geo-shape'] = 'forma geografica',
['globe-coordinate'] = 'coordinate geografiche',
['math'] = 'espressione matematica',
['monolingualtext'] = 'testo monolingua',
['quantity'] = 'quantità',
['string'] = 'stringa',
['tabular-data'] = 'tabular data',
['time'] = 'data e ora',
['url'] = 'URL',
['wikibase-item'] = 'elemento',
['wikibase-property'] = 'proprietà'
}
}
 
local p = {}
 
-------------------------------------------------------------------------------
Riga 28 ⟶ 64:
-------------------------------------------------------------------------------
 
local function formatErrorerrhandler( key msg)
local cat = mw.title.getCurrentTitle().namespace == 0 and errorCategory or ''
return '<span class="error">' .. i18n.errors[key] .. '</span>'
return string.format('<span class="error">%s</span>%s', msg, cat)
end
 
local function formatEntityIdformatList( entityIdvalues, options, formatting ordered)
local fmt = ordered and '<ol><li>%s</li></ol>' or '<ul><li>%s</li></ul>'
if formatting == 'raw' then
return #values > 0 and string.format(fmt, mw.text.listToText(values, '</li><li>', '</li><li>')) or ''
return entityId
end
 
local function formatExtLink(url)
local label = mw.wikibase.label( entityId )
local protocols = { ftp = true, http = true, https = true }
local link = mw.wikibase.sitelink( entityId )
 
if link then
local success, uri = pcall(function() return mw.uri.new(url) end)
if label then
if success and uri.protocol and protocols[uri.protocol] then
return '[[' .. link .. '|' .. label .. ']]'
local dest = tostring(uri)
else
return string.format('<span style="word-break: break-all;">[%s %s]</span>', dest, dest:gsub(uri.protocol .. '://', ''))
return '[[' .. link .. ']]'
else
end
return url
else
end
return label or ''
end
end
 
local function formatTimeformatEntityId( value, options entityId)
local label = mw.wikibase.getLabel(entityId)
local year, month, day
local siteLink = mw.wikibase.getSitelink(entityId)
local ret = ''
local ret
if entityId == mw.wikibase.getEntityIdForCurrentPage() then
ret = siteLink
elseif siteLink and label then
ret = mw.getContentLanguage():ucfirst(label) == siteLink and
string.format('[[%s]]', label) or
string.format('[[%s|%s]]', siteLink, label)
elseif siteLink then
ret = string.format('[[%s]]', siteLink)
elseif label then
ret = label
else
ret = ''
end
return ret
end
 
local function formatMonolingualtext(value, args)
local ret = ''
if not args.includelang or args.includelang:match('%f[a-z]' .. value.language .. '%f[^a-z]') then
if not args.excludelang or not args.excludelang:match('%f[a-z]' .. value.language .. '%f[^a-z]') then
ret = value.text
if args.showlang then
ret = mLanguages.lingue({ value.language }) .. '&nbsp;' .. ret
end
end
end
return ret
end
 
local function formatTimeWithPrecision(time, precision)
local months = {
'gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'
}
local ret, year, month, day
year, month, day = value.time:match( '.+(%d%d%d%d%d+)%-(%d%d)%-(%d%d).+' )
year, month, day = tonumber(year), tonumber(month), tonumber(day)
if value.precision == 9 then
if precision == 9 then
ret = tonumber( year )
ret = year
elseif value.precision == 11 then
elseif precision == 10 then
ret = mw.getLanguage('it'):formatDate('j F Y', tonumber(year) .. '-' .. month .. '-' .. day)
ret = months[month] .. ' ' .. year
ret = ret:gsub('^1%s', '1º ')
elseif precision == 11 then
end
ret = day .. ' ' .. months[month] .. ' ' .. year
if value.precision == 9 or value.precision == 11 then
ret = ret .. (value.time:subgsub('^1%s', '1)º == '-' and ' a.C.' or '')
end
if precision >= 9 and precision <= 11 then
ret = ret .. (time:sub(1, 1) == '-' and ' a.C.' or '')
end
 
return ret
end
 
local function formatGlobecoordinateformatTime( value, options args)
local ret
if options.formatting == 'latitude' then
if args.time == 'precision' then
ret = value.latitude
ret = value.precision
elseif options.formatting == 'longitude' then
elseif args.time == 'calendarmodel' then
ret = value.longitude
ret = value.calendarmodel
else
elseif args.time == 'year' and value.precision >= 9 then
ret = value.latitude .. ', ' .. value.longitude
ret = formatTimeWithPrecision(value.time, 9)
end
elseif args.time == 'month' and value.precision >= 10 then
return ret
ret = formatTimeWithPrecision(value.time, 10)
elseif args.time == 'day' and value.precision >= 11 then
ret = formatTimeWithPrecision(value.time, 11)
elseif not args.time then
ret = formatTimeWithPrecision(value.time, value.precision)
end
 
return ret or ''
end
 
local function formatFromPatternformatGlobecoordinate( strvalue, options args)
local ret
-- la parentesi () extra serve per non ritornare anche il gsub.count
if args.coord == 'latitude' then
return ( mw.ustring.gsub( options.pattern, '$1', str ) )
ret = value.latitude
elseif args.coord == 'longitude' then
ret = value.longitude
elseif args.coord == 'globe' then
ret = value.globe
else
ret = string.format('%s, %s', value.latitude, value.longitude)
end
return ret
end
 
local function getEntityIdFromValueformatFromPattern(str, value args)
local prefixpattern = ''args.pattern
pattern = mw.ustring.gsub(pattern, '\\{', '{')
if value['entity-type'] == 'item' then
pattern = mw.ustring.gsub(pattern, '\\}', '}')
prefix = 'Q'
return mw.getCurrentFrame():preprocess(mw.message.newRawMessage(pattern, str):plain())
elseif value['entity-type'] == 'property' then
prefix = 'P'
else
return formatError( 'unknown-entity-type' )
end
return prefix .. value['numeric-id']
end
 
local function formatDatavalueformatUserValue( datavaluevalue, options, formatting args)
if args.extlink then
local ret
value = formatExtLink(value)
end
return args.pattern and formatFromPattern(value, args) or value
end
 
local function getEntityIdFromValue(value)
--Use the customize handler if provided
local prefix = ''
if options['value-module'] or options['value-function'] then
if not optionsvalue['valueentity-moduletype'] or== not options['value-functionitem'] then
prefix = 'Q'
return formatError( 'unknown-value-module' )
elseif value['entity-type'] == 'property' then
end
prefix = 'P'
local formatter = require ('Module:' .. options['value-module'])
else
if formatter == nil then
error(i18n.errors['unknown-entity-type'])
return formatError( 'value-module-not-found' )
end
return prefix .. value['numeric-id']
local fun = formatter[options['value-function']]
end
if fun == nil then
 
return formatError( 'value-function-not-found' )
local function formatUnitSymbol(entityId, args)
end
local ret
return fun( datavalue.value, options )
for _, lang in ipairs({ 'mul', 'it', 'en' }) do
end
ret = p._getProperty({ 'P5061', includelang = lang, from = entityId })
if ret and ret ~= '' then
--Default formatters
break
if datavalue.type == 'wikibase-entityid' then
else
ret = formatEntityId( getEntityIdFromValue( datavalue.value ), options, formatting )
ret = nil
elseif datavalue.type == 'string' then
end
ret = datavalue.value
end
elseif datavalue.type == 'time' then
local space = ret == '°' and '' or ' '
ret = formatTime( datavalue.value, options )
if ret and args.showunitlink then
elseif datavalue.type == 'globecoordinate' then
local link = mw.wikibase.getSitelink(entityId)
ret = formatGlobecoordinate( datavalue.value, options )
if link then
elseif datavalue.type == 'quantity' then
ret = string.format('[[%s|%s]]', link, ret)
ret = tonumber(datavalue.value.amount)
end
else
end
ret = formatError( 'unknown-datavalue-type' )
return ret and (space .. ret) or ''
end
end
 
-- http://lua-users.org/wiki/SimpleRound
local function round(num, idp)
local mult = 10 ^ (idp or 0)
return math.floor(num * mult + 0.5) / mult
end
 
 
local function formatQuantity(value, args)
local ret = tonumber(value.amount)
 
if (args.unit or args.showunit) and value.unit ~= '1' then
local unitId = mw.ustring.match(value.unit, 'Q%d+')
if args.unit then
local opts = {
showunit = args.showunit,
showunitlink = args.showunitlink,
formatnum = args.formatnum,
rounding = args.rounding
}
ret = mConvert._main(ret, unitId, args.unit, opts)
else
-- se è richiesto solo il simbolo dell'unità
-- senza la conversione lo ottiene da P5061
ret = args.rounding and round(ret, args.rounding) or ret
if args.formatnum then
ret = mw.language.getContentLanguage():formatNum(ret)
end
ret = ret .. formatUnitSymbol(unitId, args)
end
elseif args.formatnum then
ret = args.rounding and round(ret, args.rounding) or ret
ret = mw.language.getContentLanguage():formatNum(ret)
elseif args.formatduration and value.unit ~= '1' then
local unitId = mw.ustring.match(value.unit, 'Q%d+')
ret = mConvert._main(ret, unitId, 'second')
ret = ret and mw.language.getContentLanguage()
:formatDuration(tonumber(ret), { 'days', 'hours', 'minutes', 'seconds' })
end
 
return ret
end
 
local function formatDatavalue(datavalue, snakdatatype, args)
local ret
 
if datavalue.type == 'wikibase-entityid' then
local entityId = getEntityIdFromValue(datavalue.value)
if args.showprop then
ret = p._getProperty({ args.showprop, n = 1, from = entityId, formatting = args.formatting }) or ''
elseif args.formatting then
local formatting = args.formatting:lower()
ret = (formatting == 'raw' or formatting == 'id') and entityId or
formatting == 'label' and mw.wikibase.getLabel(entityId) or
formatting == 'title' and (mw.wikibase.getSitelink(entityId) or '') or
error(i18n.errors['unknown-output-format'])
else
ret = formatEntityId(entityId)
end
elseif datavalue.type == 'string' then
ret = datavalue.value
if args.extlink and snakdatatype == 'url' then
ret = formatExtLink(ret)
elseif args.urlencode then
ret = mw.uri.encode(ret)
end
elseif datavalue.type == 'monolingualtext' then
ret = formatMonolingualtext(datavalue.value, args)
elseif datavalue.type == 'time' then
if args.formatting == 'raw' then
ret = datavalue.value.time
else
ret = formatTime(datavalue.value, args)
end
elseif datavalue.type == 'globecoordinate' then
ret = formatGlobecoordinate(datavalue.value, args)
elseif datavalue.type == 'quantity' then
ret = formatQuantity(datavalue.value, args)
else
error(i18n.errors['unknown-datavalue-type'])
end
 
return ret
end
 
local function formatSnak(snak, args)
if snak.snaktype == 'somevalue' then
return i18n['somevalue']
elseif snak.snaktype == 'novalue' then
return i18n['novalue']
elseif snak.snaktype == 'value' then
return formatDatavalue(snak.datavalue, snak.datatype, args)
else
error(i18n.errors['unknown-snak-type'])
end
end
 
-- È al plurale perché anche i qualifier possono avere più di un valore
-- (si ottiene inserendo due volte lo stesso qualifier)
local function formatQualifiers(claim, qualifierId, args, rawTable, retTable)
local formattedQualifiers = retTable or {}
 
if claim.qualifiers and claim.qualifiers[qualifierId] then
local qualifiers = claim.qualifiers[qualifierId]
-- con args.nq seleziona solo l'n-esimo qualifier
if args.nq then
local n = tonumber(args.nq)
qualifiers = (n and n <= #qualifiers) and { qualifiers[n] } or {}
end
-- qualifier filtrati per snaktype, default "value"
args.snaktype = args.snaktype or 'value'
for _, qualifier in ipairs(qualifiers) do
if qualifier.snaktype == args.snaktype or args.snaktype == 'all' then
local formattedQualifier = formatSnak(qualifier, args)
if formattedQualifier ~= '' then
if args.pattern then
formattedQualifier = formatFromPattern(formattedQualifier, args)
if formattedQualifier ~= '' then
table.insert(formattedQualifiers, formattedQualifier)
end
else
table.insert(formattedQualifiers, formattedQualifier)
end
end
end
end
end
 
if rawTable then
return formattedQualifiers
end
 
return #formattedQualifiers > 0 and
return ret
mw.text.listToText(formattedQualifiers, args.separator, args.conjunction) or nil
end
 
local function formatSnakappendQualifiers( snakstatement, optionstext, formatting args)
local formattedQualifiers = {}
if snak.snaktype == 'somevalue' then
local qualifierIds = mw.text.split(args.showqualifiers, ',')
return i18n['somevalue']
for _, qualifierId in ipairs(qualifierIds) do
elseif snak.snaktype == 'novalue' then
if statement.qualifiers[qualifierId] then
return i18n['novalue']
local formattedQualifier = formatQualifiers(statement, qualifierId, args)
elseif snak.snaktype == 'value' then
table.insert(formattedQualifiers, formattedQualifier)
return formatDatavalue( snak.datavalue, options, formatting )
end
else
end
return formatError( 'unknown-snak-type' )
if #formattedQualifiers > 0 then
end
text = string.format('%s (%s)', text, mw.text.listToText(formattedQualifiers, ', ', ', '))
end
return text
end
 
local function formatStatement( statement, options args)
if not statement.type or statement.type ~= 'statement' then
return formatError error( i18n.errors['unknown-claim-type' ])
end
local ret return= formatSnak( statement.mainsnak, options args)
-- eventuale showqualifiers
if args.showqualifiers and statement.qualifiers then
ret = appendQualifiers(statement, ret, args)
end
 
return ret
end
 
local function formatStatements( claims, optionsargs, rawTable)
local formattedStatements = {}
--Format statement and concat them cleanly
 
local formattedStatements = {}
for _, claim in ipairs(claims) do
local list_end, formattedStatement
local formattedStatement = formatStatement(claim, args)
if options.list or options.orderedlist then
if formattedStatement ~= '' then
if options.list then
-- eventuale pattern
formattedStatements[1] = '<ul><li>'
if args.pattern then
list_end = '</li></ul>'
formattedStatement = formatFromPattern(formattedStatement, args)
else
if formattedStatement ~= '' then
formattedStatements[1] = '<ol><li>'
table.insert(formattedStatements, formattedStatement)
list_end = '</li></ol>'
end
else
options.separator = '</li><li>'
table.insert(formattedStatements, formattedStatement)
options.conjunction = options.separator
end
end
end
for i, claim in pairs( claims ) do
if rawTable then
formattedStatement = formatStatement( claim, options )
return formattedStatements
-- eventuale pattern
end
if options.pattern then
formattedStatement = formatFromPattern( formattedStatement, options )
end
table.insert( formattedStatements, formattedStatement )
end
 
return ((args.list or if list_end then tableargs.insert(orderedlist) and #formattedStatements, list_end> 1) endand
return mw.text.listToTextformatList( formattedStatements, optionsargs.separator,orderedlist options.conjunction~= nil) or
mw.text.listToText(formattedStatements, args.separator, args.conjunction)
end
 
Riga 187 ⟶ 417:
-------------------------------------------------------------------------------
 
-- RitornaRestituisce true se lo statement contiene il qualifier richiesto con un dato valore (o uno tra più valori separati da virgola)
local function hasQualifierValue( statement, optionsqualifierId, qualifierValue)
local ret = false
for i_, qualifier in pairsipairs( statement.qualifiers[options.qualifierqualifierId] ) do
local isItem = qualifier.snaktype == 'value' and
if formatSnak( qualifier, options, 'raw' ) == options.qualifiervalue then
qualifier.datavalue.type == 'wikibase-entityid'
ret = true
local qualifierValues = mw.text.split(qualifierValue, ',')
break
for _, qualifierHas in ipairs(qualifierValues) do
end
-- per le proprietà di tipo item il confronto è eseguito sull'id
end
if formatSnak(qualifier, isItem and { formatting = 'raw' } or {}) == qualifierHas then
return ret
ret = true
break
end
end
end
return ret
end
 
-- RitornaRestituisce i claim con il rank richiesto
local function filterRankValue( claims, rank )
local ret = {}
for i_, claim in pairsipairs( claims ) do
if claim.rank == rank then
table.insert( ret, claim )
end
end
return ret
end
 
-- RitornaRestituisce una tablesequence Lua contenente gli statement per la property richiesta.,
-- anche vuota se la proprietà non esiste, o non ci sono valori che soddisfano i criteri
-- Gli statement ritornati sono eventualmente filtrati in base ai parametri:
-- ("rank", "qualifier", "qualifiertype" e, "nnoqualifier", ...).
-- Restituisce nil solo se la pagina non è collegata a un elemento Wikidata e non è indicato il from.
local function getClaims( options )
local function getClaims(propertyId, args)
local entity, claims, filteredClaims
local entityId, claims, filteredClaims
entityId = args.from or mw.wikibase.getEntityIdForCurrentPage()
-- get entity
if not entityId then
entity = mw.wikibase.getEntityObject()
return nil
if not entity then
end
error( '' ) -- error(formatError( 'entity-not-found' ))
end
-- il default rank è 'best'
args.rank = args.rank or 'best'
if args.rank == 'best' then
claims = mw.wikibase.getBestStatements(entityId, propertyId)
else
-- statements filtrati per rank
claims = mw.wikibase.getAllStatements(entityId, propertyId)
claims = filterRankValue(claims, args.rank)
end
 
-- statements filtrati per snaktype, default "value"
-- get property
args.snaktype = args.snaktype or 'value'
if not options.property then
if args.snaktype and args.snaktype ~= 'all' then
error( formatError( 'property-param-not-provided' ) )
filteredClaims = {}
end
for _, claim in ipairs(claims) do
if claim.mainsnak.snaktype == args.snaktype then
table.insert(filteredClaims, claim)
end
end
claims = filteredClaims
end
 
-- statements filtrati per qualifier
if entity.claims and entity.claims[options.property] and
if args.qualifier then
#entity.claims[options.property] > 0 then
filteredClaims = {}
claims = entity.claims[options.property]
for _, claim in ipairs(claims) do
else
if claim.qualifiers and claim.qualifiers[args.qualifier] then
error('') --TODO error?
if args.qualifiervalue then
end
if hasQualifierValue(claim, args.qualifier, args.qualifiervalue) then
table.insert(filteredClaims, claim)
end
else
table.insert(filteredClaims, claim)
end
end
end
claims = filteredClaims
end
 
-- statements filtrati per rankessere senza un qualifier
if optionsargs.ranknoqualifier then
filteredClaims = {}
if options.rank == 'best' then
for _, claim in ipairs(claims) do
filteredClaims = filterRankValue( claims, 'preferred' )
if not (claim.qualifiers and claim.qualifiers[args.noqualifier]) then
if #filteredClaims == 0 then
table.insert(filteredClaims = filterRankValue( claims, 'normal' claim)
end
end
end
else
claims = filteredClaims = filterRankValue( claims, options.rank )
end
claims = filteredClaims
end
 
-- statements filtrati per non avere un certo valore a un certo qualifier opzionale
if args.qualifieroptnovalue and args.qualifiervalue then
if options.qualifier then
filteredClaims = {}
for i_, claim in pairsipairs(claims) do
if claim.qualifiers and claim.qualifiers[optionsargs.qualifierqualifieroptnovalue] then
if not hasQualifierValue(claim, args.qualifieroptnovalue, if optionsargs.qualifiervalue) then
table.insert(filteredClaims, claim)
if hasQualifierValue( claim, options ) then
end
table.insert( filteredClaims, claim )
else
end
table.insert(filteredClaims, claim)
else
end
table.insert( filteredClaims, claim )
end
end
claims = filteredClaims
end
end
claims = filteredClaims
end
 
-- con optionsargs.qualifiertype=latest ritornarestituisce solo il più recente
if optionsargs.qualifier and optionsargs.qualifiertype == 'latest' then
local latest, latestTime
for i_, claim in pairsipairs( claims ) do
if claim.qualifiers and claim.qualifiers[optionsargs.qualifier] then
for j_, qualifier in pairsipairs( claim.qualifiers[optionsargs.qualifier] ) do
if qualifier.datavalue.type == 'time' then
if not latestTime or qualifier.datavalue.value.time > latestTime then
latest = claim
latestTime = qualifier.datavalue.value.time
end
end
end
end
end
end
end
end
end
claims = latest and { latest } or {}
end
 
-- con optionsargs.n ritornarestituisce solo l'n-esimo elemento
if optionsargs.n then
local n = tonumber( optionsargs.n )
claims = (n and n <= #claims) and { claims[n] } or {}
end
 
return claims
end
 
-------------------------------------------------------------------------------
-- Funzioni esportate per altri APImoduli
-------------------------------------------------------------------------------
 
function p._getClaims(propertyId, args)
local p = {}
return getClaims(propertyId, args or {})
end
 
function p._formatStatement(statement, args)
-- Funzione di utilità, ritorna gli argomenti passati al modulo
return formatStatement(statement, args or {})
-- scartando quelli con nome valorizzati a stringhe vuote.
-- Trasforma inoltre i valori di property e qualifier in uppercase.
local function getArgs( frame )
local args = {}
for k, v in pairs( frame.args ) do
if v ~= '' then
if k == "property" or k == "qualifier" then
v = string.upper( v )
end
args[k] = v
end
end
return args
end
 
function p._formatQualifiers(claim, qualifierId, args, rawTable, retTable)
-- Entry-point per {{#invoke:Wikidata|formatStatements}}
return formatQualifiers(claim, qualifierId, args or {}, rawTable, retTable)
function p.formatStatements( frame )
end
local args, ret, claims
 
-- Restituisce il valore di una proprietà di Wikidata oppure nil se l'entity o
-- la proprietà non esistono, o se per parametri di selezione gli statement sono zero.
function p._getProperty(args, rawTable)
local propertyId, value, claims, ret
 
-- parametri posizionali
args = getArgs( frame )
propertyId = args[1] and string.upper(args[1])
if not propertyId then
error(i18n.errors['property-param-not-provided'], 2)
end
value = args[2]
-- fix uppercase
args.qualifier = args.qualifier and string.upper(args.qualifier)
 
if value then
-- if parameter value is already set, use it
ret = formatUserValue(value, args)
if args.value then
elseif args.wd ~= 'no' then
return args.pattern and formatFromPattern( args.value, args ) or args.value
claims = getClaims(propertyId, args)
end
ret = (claims and #claims > 0) and formatStatements(claims, args, rawTable) or nil
end
-- get claims
ret, claims = pcall( getClaims, args )
if not ret then
return claims:match( '.+%d:%s(.+)$' )
end
 
return ret
return formatStatements( claims, args )
end
 
-- Restituisce il valore di un qualifier di una proprietà di Wikidata,
-- Entry-point per {{#invoke:Wikidata|getQualifier}}
-- o nil se l'entity o la proprietà non esistono, o se per parametri di selezione non ci sono risultati.
function p.getQualifier( frame )
function p._getQualifier(args)
local args, ret, claims, formattedQualifier, formattedQualifiers
local propertyId, qualifierId, value, claims, ret
 
-- parametri posizionali
args = getArgs( frame )
propertyId = args[1] and string.upper(args[1])
if not propertyId then
error(i18n.errors['property-param-not-provided'], 2)
end
qualifierId = args[2] and string.upper(args[2])
if not qualifierId then
error(i18n.errors['qualifier-param-not-provided'], 2)
end
value = args[3]
 
if value then
-- if parameter value is already set, use it
ret = formatUserValue(value, args)
if args.value then
elseif args.wd ~= 'no' then
return args.pattern and formatFromPattern( args.value, args ) or args.value
claims = getClaims(propertyId, args)
end
if claims and #claims > 0 then
local formattedQualifiers = {}
for _, claim in ipairs(claims) do
formattedQualifiers = formatQualifiers(claim, qualifierId, args, true, formattedQualifiers)
end
ret = #formattedQualifiers > 0 and
mw.text.listToText(formattedQualifiers, args.separator, args.conjunction) or nil
end
end
 
return ret
-- get qualifier name
end
if not args.qualifier then
return formatError( 'qualifier-param-not-provided' )
end
 
-- Restituisce l'indice dello statement con il valore richiesto, o nil se non trovato.
-- get claims
function p._indexOf(args)
ret, claims = pcall( getClaims, args )
local ret, propertyId, value, claims
if not ret then
return claims:match( '.+%d:%s(.+)$' )
end
 
-- parametri posizionali
-- get qualifiers and format them
propertyId = args[1] and string.upper(args[1])
formattedQualifiers = {}
if not propertyId then
for i, claim in pairs( claims ) do
error(i18n.errors['property-param-not-provided'], 2)
if claim.qualifiers and claim.qualifiers[args.qualifier] then
end
for j, qualifier in pairs( claim.qualifiers[args.qualifier] ) do
value = args[2]
formattedQualifier = formatSnak( qualifier, args )
if not value then
if args.pattern then
error(i18n.errors['value-param-not-provided'], 2)
formattedQualifier = formatFromPattern( formattedQualifier, args )
end
end
table.insert( formattedQualifiers, formattedQualifier )
end
end
end
 
claims = getClaims(propertyId, args)
return mw.text.listToText( formattedQualifiers, args.separator, args.conjunction )
if claims and #claims > 0 then
args.formatting = 'raw'
for i, claim in ipairs(claims) do
if formatStatement(claim, args) == value then
ret = i
break
end
end
end
 
return ret
end
 
-- Restituisce il numero di statement di una proprietà di Wikidata.
-- Entry-point per {{#invoke:Wikidata|N}}
function p.N_N( frame args)
local entity, propertypropertyId, countclaims
 
-- parametri posizionali
property = string.upper( frame.args[1] )
propertyId = args[1] and string.upper(args[1])
entity = mw.wikibase.getEntityObject()
if not propertyId then
if entity and entity.claims and entity.claims[property] then
error(i18n.errors['property-param-not-provided'], 2)
count = #entity.claims[property]
end
-- get claims
claims = getClaims(propertyId, args)
 
return claims and return count#claims or 0
end
 
-- Restituisce true se la propriertà specificata ha come valore
-- almeno uno tra gli entityId passati come argomento.
function p._propertyHasEntity(propertyId, args)
local statements = p._getProperty({ propertyId, from = args.from, formatting = 'raw' }, true)
if statements then
for _, statement in ipairs(statements) do
for _, entityId in ipairs(args) do
if statement == entityId then
return true
end
end
end
 
-- Se non è stato trovato alcun valore, controlla se questo sia ereditato
-- tramite la proprietà "sottoclasse di" (P279) scavando in profondità
-- fino all'esaurirsi del numero specificato in args.recursion.
--[[ TODO: Valutare se sia opportuna una ricerca ricorsiva potenzialmente infinita.
Per farlo si può aggiungere un parametro (opzionale) maxDepth
che svolga l'attuale funzione di recursion e cambiare quest'ultimo
in un parametro booleano.
]]
args.recursion = tonumber(args.recursion) or 0
if args.recursion > 0 then
local recursion = args.recursion
if type(args.loadedEntities) ~= 'table' then
args.loadedEntities = setmetatable({}, {
__newindex = function(t, k, v)
rawset(t, k, v)
rawset(t, #t+1, k)
end })
args.loadedEntities[args.from or mw.wikibase.getEntityIdForCurrentPage()] = true
end
for _, statement in ipairs(statements) do
if not args.loadedEntities[statement] then
args.loadedEntities[statement] = true
args.recursion = args.recursion - 1
args.from = statement
if p._propertyHasEntity('P279', args) then
return true, args.loadedEntities
end
args.recursion = recursion
end
end
end
end
 
return false, args.loadedEntities
end
 
-- Restituisce true se la proprietà P31 (instance of) ha come valore almeno uno tra gli entityId specificati
function p._instanceOf(args)
return p._propertyHasEntity('P31', args)
end
 
-- Restituisce true se la proprietà P279 (subclass of) ha come valore almeno uno tra gli entityId specificati
function p._subclassOf(args)
return p._propertyHasEntity('P279', args)
end
 
-- Restituisce l'etichetta di un item o di una proprietà Wikidata.
function p._getLabel(args)
local entityId = args[1] and string.upper(args[1])
local ret
if args[2] then
ret = mw.wikibase.getLabelByLang(entityId, args[2])
else
ret = mw.wikibase.getLabel(entityId)
end
return ret
end
 
-- Restituisce la descrizione di un item o di una proprietà Wikidata.
function p._getDescription(args)
local entityId = args[1] and string.upper(args[1])
local ret = mw.wikibase.getDescription(entityId)
return ret
end
 
-- Restituisce il titolo della pagina collegata a un dato item Wikidata.
function p._getLink(args)
-- parametri posizionali
local entityId = args[1] and string.upper(args[1])
if not entityId then
error(i18n.errors['entityid-param-not-provided'], 2)
end
return entityId:sub(1, 1) == 'Q' and formatEntityId(entityId) or nil
end
 
-- Restituisce il datatype di una proprietà Wikidata.
function p._getDatatype(args)
local propertyId, entity
 
-- parametri posizionali
propertyId = args[1] and string.upper(args[1])
if not propertyId then
error(i18n.errors['property-param-not-provided'], 2)
end
 
entity = mw.wikibase.getEntity(propertyId)
if not entity then
error(i18n.errors['entity-not-found'], 2)
end
 
if not i18n.datatypes[entity.datatype] then
error(i18n.errors['unknown-datavalue-type'], 2)
end
 
return i18n.datatypes[entity.datatype]
end
 
-- Restituisce l'ID dell'item Wikidata collegato alla pagina corrente o a una pagina specificata
-- (nota: se il parametro followRedirects è valorizzato con "no", segue i redirect fermandosi al primo redirect collegato a un elemento)
function p._getId(args)
local ret
local followRedirects = not args.followRedirects or args.followRedirects ~= "no"
if args[1] then
local title = mw.title.new(args[1])
while title do
local id = mw.wikibase.getEntityIdForTitle(title.prefixedText)
if id then
ret = id
break
else
title = followRedirects and title.redirectTarget or nil
end
end
else
ret = mw.wikibase.getEntityIdForCurrentPage()
end
return ret
end
 
-------------------------------------------------------------------------------
-- Funzioni esportate per i template
-------------------------------------------------------------------------------
 
-- Funzione per il template {{Wikidata}}
function p.getProperty(frame)
return select(2, xpcall(function()
return p._getProperty(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataQ}}
function p.getQualifier(frame)
return select(2, xpcall(function()
return p._getQualifier(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataIdx}}
function p.indexOf(frame)
return select(2, xpcall(function()
return p._indexOf(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataN}}
function p.N(frame)
return select(2, xpcall(function()
return p._N(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataLabel}}
function p.getLabel(frame)
return select(2, xpcall(function()
return p._getLabel(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataDescription}}
function p.getDescription(frame)
return select(2, xpcall(function()
return p._getDescription(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataLink}}
function p.getLink(frame)
return select(2, xpcall(function()
return p._getLink(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataIstanza}}
function p.instanceOf(frame)
return select(2, xpcall(function()
return p._instanceOf(getArgs(frame, { parentOnly = true })) and 1 or ''
end, errhandler))
end
 
-- Funzione per il template {{WikidataTipo}}
function p.getDatatype(frame)
return select(2, xpcall(function()
return p._getDatatype(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataId}}
function p.getId(frame)
return select(2, xpcall(function()
return p._getId(getArgs(frame, { parentOnly = true }))
end, errhandler))
end
 
-- Funzione per il template {{WikidataValido}}
function p.checkProperty(frame)
return select(2, xpcall(function()
return p._N(getArgs(frame, { parentOnly = true })) > 0 and 1 or ''
end, errhandler))
end
 
-- Funzione per il template {{WikidataClasse}}
function p.propertyHasEntity(frame)
local args = getArgs(frame)
local propertyId = args[1]
return select(2, xpcall(function()
return p._propertyHasEntity(propertyId, args) and 1 or ''
end, errhandler))
end
 
return p