Modulo:Wikidata: differenze tra le versioni

Da Wikiquote, aforismi e citazioni in libertà.
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 ''
end

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 ('Module:' .. options['value-module'])
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.getEntityObject()
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
-- argomenti passati indirettamente come parametri del template invocante
local parent = frame:getParent()
local parent = frame:getParent()
local parentArgs = parent and parent.args or {}
local parentArgs = parent and parent.args or {}
for k, v in pairs(parentArgs) do
for k, v in pairs(parentArgs) do
if v ~= '' then
args[k] = v
if v ~= '' then
args[k] = v
end
end
end
-- argomenti passati direttamente come parametri di #invoke
end
for k, v in pairs(frame.args) do

if v ~= '' then
-- argomenti passati direttamente come parametri di #invoke
args[k] = v
for k, v in pairs(frame.args) do
end
if v ~= '' then
args[k] = v
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 = { property = true, qualifier = true, qualifiervalue = true }
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
-- controllo tramite identificatore per tipo di dato "entità" (proprietà/elemento)
local options = { formatting = 'nolink' }
-- controllo tramite identificatore per tipo di dato "elemento"
if datavalue.type == 'wikibase-entityid' then
if datavalue.type == 'wikibase-entityid' then
checkvalue = formatEntityId(getEntityIdFromValue(datavalue.value), options, 'raw')
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)
local options = { formatting = 'nolink' }
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ò restituire nil 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