Modulo:Wikidata: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
preparo nuove caratteristiche dell'estensione |
aggiorno |
||
Riga 39: | Riga 39: | ||
local label = mw.wikibase.label(entityId) |
local label = mw.wikibase.label(entityId) |
||
if options.formatting == 'nolink' then |
|||
return label or '' |
|||
⚫ | |||
local link = mw.wikibase.sitelink(entityId) |
local link = mw.wikibase.sitelink(entityId) |
||
if link then |
if link and options.formatting ~= 'nolink' then |
||
if label then |
if label then |
||
return '[[' .. link .. '|' .. label .. ']]' |
return '[[' .. link .. '|' .. label .. ']]' |
||
Riga 112: | Riga 108: | ||
return formatError('unknown-value-module') |
return formatError('unknown-value-module') |
||
end |
end |
||
local formatter = require (' |
local formatter = require ('Modulo:' .. options['value-module']) |
||
if formatter == nil then |
if formatter == nil then |
||
return formatError('value-module-not-found') |
return formatError('value-module-not-found') |
||
Riga 223: | Riga 219: | ||
-- "rank", "qualifier", "qualifiertype" e "n" |
-- "rank", "qualifier", "qualifiertype" e "n" |
||
local function getClaims(options) |
local function getClaims(options) |
||
local entity, claims, filteredClaims |
local entityId, entity, claims, filteredClaims |
||
-- get entity |
-- get entity |
||
entityId = options.entityId and string.upper(options.entityId) |
|||
entity = mw.wikibase. |
entity = mw.wikibase.getEntity(entityId) |
||
if not entity then |
if not entity then |
||
error('') -- error(formatError('entity-not-found')) |
error('') -- error(formatError('entity-not-found')) |
||
Riga 307: | Riga 304: | ||
-- Funzione di utilità, ritorna gli argomenti passati al modulo |
-- Funzione di utilità, ritorna gli argomenti passati al modulo |
||
-- scartando quelli valorizzati a stringhe vuote |
-- scartando quelli valorizzati a stringhe vuote |
||
local function getArgs(frame) |
local function getArgs(frame) |
||
local args = {} |
local args = {} |
||
if frame == mw.getCurrentFrame() then |
|||
-- argomenti passati indirettamente come parametri del template invocante |
|||
local parent = frame:getParent() |
|||
local parentArgs = parent and parent.args or {} |
|||
for k, v in pairs(parentArgs) do |
|||
⚫ | |||
if v ~= '' then |
|||
⚫ | |||
⚫ | |||
end |
end |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
args[k] = v |
|||
⚫ | |||
⚫ | |||
if v ~= '' then |
|||
⚫ | |||
end |
end |
||
else |
|||
args = frame |
|||
end |
end |
||
-- trasforma i valori di property, qualifier e qualifiervalue in maiuscolo |
-- trasforma i valori di property, qualifier e qualifiervalue in maiuscolo |
||
local toUpper = { |
local toUpper = { |
||
property = true, |
|||
qualifier = true, |
|||
qualifiervalue = true |
|||
} |
|||
for k, v in pairs(args) do |
for k, v in pairs(args) do |
||
if toUpper[k] then |
if toUpper[k] then |
||
Riga 349: | Riga 353: | ||
-- if parameter value is already set, use it |
-- if parameter value is already set, use it |
||
if args.value then |
if args.value then |
||
return not(args.novaluepattern) and args.pattern and formatFromPattern(args.value, args) |
return not(args.novaluepattern) -- if parameter novaluepattern is not set |
||
and args.pattern and formatFromPattern(args.value, args) |
|||
or args.value |
or args.value |
||
end |
end |
||
Riga 370: | Riga 375: | ||
-- if parameter value is already set, use it |
-- if parameter value is already set, use it |
||
if args.value then |
if args.value then |
||
return not(args.novaluepattern) and args.pattern and formatFromPattern(args.value, args) |
return not(args.novaluepattern) -- if parameter novaluepattern is not set |
||
and args.pattern and formatFromPattern(args.value, args) |
|||
or args.value |
or args.value |
||
end |
end |
||
Riga 439: | Riga 445: | ||
if claim and claim.mainsnak and claim.mainsnak.datavalue then |
if claim and claim.mainsnak and claim.mainsnak.datavalue then |
||
local datavalue = claim.mainsnak.datavalue |
local datavalue = claim.mainsnak.datavalue |
||
⚫ | |||
⚫ | |||
⚫ | |||
if datavalue.type == 'wikibase-entityid' then |
if datavalue.type == 'wikibase-entityid' then |
||
checkvalue = |
checkvalue = getEntityIdFromValue(datavalue.value) |
||
if checkvalue == string.upper(value) then |
if checkvalue == string.upper(value) then |
||
return n |
return n |
||
end |
end |
||
end |
end |
||
-- controllo testuale tra stringhe |
-- controllo testuale tra stringhe (testo semplice senza wikilink) |
||
⚫ | |||
checkvalue = formatDatavalue(datavalue, options) |
checkvalue = formatDatavalue(datavalue, options) |
||
if tostring(checkvalue) == value then |
if tostring(checkvalue) == value then |
Versione delle 12:57, 18 apr 2015
Il modulo Wikidata implementa le funzionalità dei template {{Wikidata}}.
Utilizzo da un altro modulo
Il modulo può essere usato anche da un altro modulo tramite "require". È sufficiente inserire all'inizio del modulo:
local mWikidata = require('Modulo:Wikidata')
Le funzioni hanno gli stessi nomi di quelle utilizzate dai template ma con un underscore iniziale e ricevono come argomento, invece del frame, una table con cui specificare gli argomenti.
_getProperty(args, rawTable)
: per l'utilizzo della tabella args vedere il manuale del template {{Wikidata}}. Il parametro aggiuntivo rawTable, se valorizzato a true, fa sì che le dichiarazioni non vengano unite in un'unica stringa come per il template (separate dalla virgola e con la "e" prima dell'ultima), ma venga invece restituita una sequence, contenente le stringhe separate per ciascuna dichiarazione._getQualifier(args)
_indexOf(args)
_N(args)
_getLabel(args)
_getLink(args)
_getDatatype(args)
_getId(args)
_instanceOf(args)
_subClassOf(args)
A queste si aggiungono tre funzioni specifiche del modulo, che permettono di iterare sulle dichiarazioni di una proprietà:
_getClaims(property, args)
: restituisce una sequence con le dichiarazioni di una proprietà, come _getProperty, ma senza formattarle. Per gli argomenti utilizzabili nella tabella args vedere i parametri di selezione nel manuale del template {{Wikidata}}. Può restituirenil
nel caso in cui la pagina non sia collegata a Wikidata._formatStatement(statement, args)
: formatta una dichiarazione (parametro statement) ottenuta tramite getClaims. Per l'utilizzo della tabella args vedere i parametri di formattazione nel manuale del template {{Wikidata}}._formatQualifiers(claim, qualifier, args, rawTable, retTable)
: formatta un qualificatore (parametro qualifier) di una dichiarazione (parametro claim) ottenuta tramite getClaims. Per l'utilizzo della tabella args vedere i parametri di formattazione nel manuale del template {{Wikidata}}. Il parametro rawTable, se valorizzato a true, fa sì che eventuali valori multipli di un qualificatore vengano restituiti come sequence invece che come unica stringa (con retTable è possibile specificare una sequence già esistente).
- Esempio
local mWikidata = require('Modulo:Wikidata')
local p = {}
function p.main(frame)
local capitale, data, stati, italia, onu
-- utilizzo della funzione getProperty
capitale = mWikidata._getProperty( { 'P36', from = 'Q183' } )
-- utilizzo della funzione getQualifier
data = mWikidata._getQualifier( { 'P36', 'P580', from = 'Q183' } )
-- utilizzo della funzione N
stati = mWikidata._N( { 'P47', from = 'Q183' } )
-- utilizzo della funzione indexOf
italia = mWikidata._indexOf( { 'P47', 'Q38', from = 'Q183' } )
-- utilizzo della funzione instanceOf
onu = mWikidata._instanceOf( { 'Q160016', from = 'Q183' } )
return string.format('La capitale della Germania è %s, dal %s. ' ..
'Confina con %s Stati, con l\'Italia: %s. ' ..
'Membro delle Nazioni Unite: %s.',
capitale, data, stati, italia and 'si' or 'no', onu and 'sì' or 'no')
end
return p
- Esempio con getClaims, formatStatement e formatQualifiers
local mWikidata = require('Modulo:Wikidata')
local p = {}
function p.main(frame)
local scuole = {}
local claims
claims = mWikidata._getClaims('P69', { from = 'Q42' })
for _, claim in ipairs(claims) do
local scuola = mWikidata._formatStatement(claim)
local inizio = mWikidata._formatQualifiers(claim, 'P580')
local fine = mWikidata._formatQualifiers(claim, 'P582')
table.insert(scuole, string.format('%s dal %s al %s', scuola, inizio, fine))
end
return 'Douglas Adams ha frequentato: ' .. table.concat(scuole, ', ')
end
return p
--[[
* Modulo per implementare le funzionalità dei template {{Wikidata}} e {{Wikidata Check}}.
* Permette di accedere a Wikidata in modo più avanzato rispetto a {{#property}}.
* Il modulo è stato importato inizialmente da:
* http://test2.wikipedia.org/w/index.php?title=Module:Wikidata&oldid=52322
]]
-- Messaggi di errore
local i18n = {
["errors"] = {
["property-param-not-provided"] = "Parametro ''property'' non fornito.",
["qualifier-param-not-provided"] = "Parametro ''qualifier'' non fornito.",
["entity-not-found"] = "Entità non trovata.",
["unknown-claim-type"] = "Tipo asserzione sconosciuta.",
["unknown-snak-type"] = "Tipo di snak sconosciuto.",
["unknown-datavalue-type"] = "Tipo di dato sconosciuto.",
["unknown-entity-type"] = "Tipo di entità sconosciuta.",
["unknown-value-module"] = "Devi impostare entrambi i parametri: ''value-module'' e ''value-function''.",
["value-module-not-found"] = "Modulo indicato da ''value-module'' non trovato.",
["value-function-not-found"] = "Funzione indicata da ''value-function'' non trovata."
},
["somevalue"] = "''valore sconosciuto''",
["novalue"] = "''nessun valore''"
}
-------------------------------------------------------------------------------
-- Formatters
-------------------------------------------------------------------------------
local function formatError(key)
return '<span class="error">' .. i18n.errors[key] .. '</span>'
end
local function formatEntityId(entityId, options, formatting)
if formatting == 'raw' then
return entityId
end
local label = mw.wikibase.label(entityId)
local link = mw.wikibase.sitelink(entityId)
if link and options.formatting ~= 'nolink' then
if label then
return '[[' .. link .. '|' .. label .. ']]'
else
return '[[' .. link .. ']]'
end
else
return label or ''
end
end
local function formatTime(value, options)
local year, month, day
local ret = ''
year, month, day = value.time:match('.+(%d%d%d%d%d)%-(%d%d)%-(%d%d).+')
if value.precision == 9 then
ret = tonumber(year)
elseif value.precision == 10 then
ret = mw.getLanguage('it'):formatDate('F Y', tonumber(year) .. '-' .. month)
elseif value.precision == 11 then
ret = mw.getLanguage('it'):formatDate('j F Y', tonumber(year) .. '-' .. month .. '-' .. day)
ret = ret:gsub('^1%s', '1º ')
end
if value.precision >= 9 and value.precision <= 11 then
ret = ret .. (value.time:sub(1, 1) == '-' and ' a.C.' or '')
end
return ret
end
local function formatGlobecoordinate(value, options)
local ret
if options.formatting == 'latitude' then
ret = value.latitude
elseif options.formatting == 'longitude' then
ret = value.longitude
else
ret = value.latitude .. ', ' .. value.longitude
end
return ret
end
local function formatFromPattern(str, options)
-- la parentesi () extra serve per non ritornare anche il gsub.count
return (mw.ustring.gsub(options.pattern, '$1', str))
end
local function getEntityIdFromValue(value)
local prefix = ''
if value['entity-type'] == 'item' then
prefix = 'Q'
elseif value['entity-type'] == 'property' then
prefix = 'P'
else
return formatError('unknown-entity-type')
end
return prefix .. value['numeric-id']
end
local function formatDatavalue(datavalue, options, formatting)
local ret
--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 ('Modulo:' .. options['value-module'])
if formatter == nil then
return formatError('value-module-not-found')
end
local funct = formatter[options['value-function']]
if funct == nil then
return formatError('value-function-not-found')
end
return funct(datavalue.value, options)
end
--Default formatters
if datavalue.type == 'wikibase-entityid' then
ret = formatEntityId(getEntityIdFromValue(datavalue.value), options, formatting)
elseif datavalue.type == 'string' then
ret = datavalue.value
elseif datavalue.type == 'monolingualtext' then
ret = datavalue.value.text
elseif datavalue.type == 'time' then
ret = formatTime(datavalue.value, options)
elseif datavalue.type == 'globecoordinate' then
ret = formatGlobecoordinate(datavalue.value, options)
elseif datavalue.type == 'quantity' then
ret = tonumber(datavalue.value.amount)
else
ret = formatError('unknown-datavalue-type')
end
return ret
end
local function formatSnak(snak, options, formatting)
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, options, formatting)
else
return formatError('unknown-snak-type')
end
end
local function formatStatement(statement, options)
if not statement.type or statement.type ~= 'statement' then
return formatError('unknown-claim-type')
end
return formatSnak(statement.mainsnak, options)
end
local function formatStatements(claims, options)
--Format statement and concat them cleanly
local formattedStatements = {}
local list_end, formattedStatement
if options.list or options.orderedlist then
if options.list then
formattedStatements[1] = '<ul><li>'
list_end = '</li></ul>'
else
formattedStatements[1] = '<ol><li>'
list_end = '</li></ol>'
end
options.separator = '</li><li>'
options.conjunction = options.separator
end
for i, claim in pairs(claims) do
formattedStatement = formatStatement(claim, options)
-- eventuale pattern
if options.pattern then
formattedStatement = formatFromPattern(formattedStatement, options)
end
table.insert(formattedStatements, formattedStatement)
end
if list_end then table.insert(formattedStatements, list_end) end
return mw.text.listToText(formattedStatements, options.separator, options.conjunction)
end
-------------------------------------------------------------------------------
-- Lettura e selezione statement
-------------------------------------------------------------------------------
-- Ritorna true se lo statement contiene il qualifier richiesto con un dato valore
local function hasQualifierValue(statement, options)
local ret = false
for i, qualifier in pairs(statement.qualifiers[options.qualifier]) do
if formatSnak(qualifier, options, 'raw') == options.qualifiervalue then
ret = true
break
end
end
return ret
end
-- Ritorna i claim con il rank richiesto
local function filterRankValue(claims, rank)
local ret = {}
for i, claim in pairs(claims) do
if claim.rank == rank then
table.insert(ret, claim)
end
end
return ret
end
-- Ritorna una table contenente gli statement per la property richiesta.
-- Gli statement ritornati sono eventualmente filtrati in base ai parametri:
-- "rank", "qualifier", "qualifiertype" e "n"
local function getClaims(options)
local entityId, entity, claims, filteredClaims
-- get entity
entityId = options.entityId and string.upper(options.entityId)
entity = mw.wikibase.getEntity(entityId)
if not entity then
error('') -- error(formatError('entity-not-found'))
end
-- get property
if not options.property then
error(formatError('property-param-not-provided'))
end
if entity.claims and entity.claims[options.property] and
#entity.claims[options.property] > 0 then
claims = entity.claims[options.property]
else
error('') --TODO error?
end
-- statements filtrati per rank
if options.rank then
if options.rank == 'best' then
filteredClaims = filterRankValue(claims, 'preferred')
if #filteredClaims == 0 then
filteredClaims = filterRankValue(claims, 'normal')
end
else
filteredClaims = filterRankValue(claims, options.rank)
end
claims = filteredClaims
end
-- statements filtrati per qualifier
if options.qualifier then
filteredClaims = {}
for i, claim in pairs(claims) do
if claim.qualifiers and claim.qualifiers[options.qualifier] then
if options.qualifiervalue then
if hasQualifierValue(claim, options) then
table.insert(filteredClaims, claim)
end
else
table.insert(filteredClaims, claim)
end
end
end
claims = filteredClaims
end
-- con options.qualifiertype=latest ritorna solo il più recente
if options.qualifier and options.qualifiertype == 'latest' then
local latest, latestTime
for i, claim in pairs(claims) do
if claim.qualifiers and claim.qualifiers[options.qualifier] then
for j, qualifier in pairs(claim.qualifiers[options.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
claims = latest and {latest} or {}
end
-- con options.n ritorna solo l'n-esimo elemento
if options.n then
local n = tonumber(options.n)
claims = (n and n <= #claims) and {claims[n]} or {}
end
return claims
end
-------------------------------------------------------------------------------
-- API
-------------------------------------------------------------------------------
local p = {}
-- Funzione di utilità, ritorna gli argomenti passati al modulo
-- scartando quelli valorizzati a stringhe vuote
local function getArgs(frame)
local args = {}
if frame == mw.getCurrentFrame() then
-- argomenti passati indirettamente come parametri del template invocante
local parent = frame:getParent()
local parentArgs = parent and parent.args or {}
for k, v in pairs(parentArgs) do
if v ~= '' then
args[k] = v
end
end
-- argomenti passati direttamente come parametri di #invoke
for k, v in pairs(frame.args) do
if v ~= '' then
args[k] = v
end
end
else
args = frame
end
-- trasforma i valori di property, qualifier e qualifiervalue in maiuscolo
local toUpper = {
property = true,
qualifier = true,
qualifiervalue = true
}
for k, v in pairs(args) do
if toUpper[k] then
args[k] = string.upper(v)
end
end
-- rank impostato a best per default
args.rank = args.rank or 'best'
return args
end
-- Entry-point per {{#invoke:Wikidata|formatStatements}}
function p.formatStatements(frame)
local args, ret, claims
args = getArgs(frame)
-- if parameter value is already set, use it
if args.value then
return not(args.novaluepattern) -- if parameter novaluepattern is not set
and args.pattern and formatFromPattern(args.value, args)
or args.value
end
-- get claims
ret, claims = pcall(getClaims, args)
if not ret then
return claims:match('.+%d:%s(.+)$')
end
return formatStatements(claims, args)
end
-- Entry-point per {{#invoke:Wikidata|getQualifier}}
function p.getQualifier(frame)
local args, ret, claims, formattedQualifier, formattedQualifiers
args = getArgs(frame)
-- if parameter value is already set, use it
if args.value then
return not(args.novaluepattern) -- if parameter novaluepattern is not set
and args.pattern and formatFromPattern(args.value, args)
or args.value
end
-- get qualifier name
if not args.qualifier then
return formatError('qualifier-param-not-provided')
end
-- get claims
ret, claims = pcall(getClaims, args)
if not ret then
return claims:match('.+%d:%s(.+)$')
end
-- get qualifiers and format them
formattedQualifiers = {}
for i, claim in pairs(claims) do
if claim.qualifiers and claim.qualifiers[args.qualifier] then
for j, qualifier in pairs(claim.qualifiers[args.qualifier]) do
formattedQualifier = formatSnak(qualifier, args)
if args.pattern then
formattedQualifier = formatFromPattern(formattedQualifier, args)
end
table.insert(formattedQualifiers, formattedQualifier)
end
end
end
return mw.text.listToText(formattedQualifiers, args.separator, args.conjunction)
end
-- Entry-point per {{#invoke:Wikidata|N}}
function p.N(frame)
local property, count, entity, entityId
property = frame.args[1] and string.upper(frame.args[1])
if not property then
return formatError('property-param-not-provided')
end
entityId = frame.args.entityId and string.upper(frame.args.entityId)
entity = mw.wikibase.getEntity(entityId)
if entity and entity.claims and entity.claims[property] then
count = #entity.claims[property]
end
return count or 0
end
-- Entry-point per {{#invoke:Wikidata|checkStatements}}
function p.checkStatements(frame)
local property, value, checkvalue, entity, entityId
property = frame.args.property and string.upper(frame.args.property)
if not property then
return formatError('property-param-not-provided')
end
value = frame.args.value
entityId = frame.args.entityId and string.upper(frame.args.entityId)
entity = mw.wikibase.getEntity(entityId)
if entity and entity.claims and entity.claims[property] then
local claims = entity.claims[property]
for n, claim in pairs(claims) do
if claim and claim.mainsnak and claim.mainsnak.datavalue then
local datavalue = claim.mainsnak.datavalue
-- controllo tramite identificatore per tipo di dato "entità" (proprietà/elemento)
if datavalue.type == 'wikibase-entityid' then
checkvalue = getEntityIdFromValue(datavalue.value)
if checkvalue == string.upper(value) then
return n
end
end
-- controllo testuale tra stringhe (testo semplice senza wikilink)
local options = { formatting = 'nolink' }
checkvalue = formatDatavalue(datavalue, options)
if tostring(checkvalue) == value then
return n
end
end
end
end
return ''
end
return p