Ir al contenido

Módulo:Wikidata

De Wikisource, la biblioteca libre.
Documentación del módulo


Uso

Este módulo devuelve el valor o valores con o sin formato específico a una propiedad de Wikidata.

Funciones

  • claim: Devuelve el valor (o los valores) de una declaración o de un calificador con un formato por defecto según el tipo de dato.
  • badge: Devuelve el valor de la insígnia (badge) de una obra enlazada en Wikidata.

Función claim

Devuelve el valor (o los valores) de una declaración o de un calificador con un formato por defecto según el tipo de dato. Por defecto está referido al ítem de Wikidata (Qid) asociado a la página actual.

Sintaxis completa:

{{#invoke:Wikidata|claim|item= |lang= |property= |qualifier= |list= |formatting= }}

Parámetros generales

  • item= (opcional) Permite indicar un ítem (Qid) diferente al ítem asociado a la página actual. Ha de usarse con moderación por su alto consumo de recursos.
  • lang= (opcional) Permite indicar el código de un idioma determinado.
  • property= (obligatorio) Identificador de la propiedad de la declaración (Pid). Por ejemplo "P50".
  • qualifier= (opcional) Calificador (Pid) del valor de la propiedad.
  • list= (opcional):
    • list=true (por defecto): Muestra una lista de todos los valores, separados con un "separador" por defecto y una "conjunción" predefinida.
    • list=false: sólo recuperará un valor, generalmente el de mayor rango o el más antiguo.
  • formatting= (opcional): tipo de formato. Depende del valor de la entidad (ver código fuente). Ejemplos habituales: "raw", "label", "sitelink"...
  • tabla=true (opcional): Devuelve los valores como elementos en una tabla (array) de Lua, para uso interno de otros módulos.

Ejemplos

  • Wikidata.claim{item=Q107297266, property="P50", lang="es", list=true} devuelve los autores (propiedad P50) del ítem Q107297266 (edición de 1864 de El Robinson suizo).


Función badge

Devuelve la insignia (badge) de una obra enlazada en Wikidata a partir de su identificador o del valor correspondiente en el índice. Valores devueltos posibles: no corregido (no corregido), corregida (corregida), validada (validada), o problemática (problemática). Ha de existir la página y la insignia debe corresponder a uno de estas cuatro (si no, el valor devuelto es nulo).

{{#invoke:Wikidata|badge|qid=|indicator=|ws=}}

  • qid= es el identificador de la obra en Wikidata.
  • indicator= si tiene cualquier valor, envuelve la insignia en la etiqueta <indicator> y la muestra en la parte superior de la página (no funciona en móviles, solo escritorio).
  • ws= devuelve la insignia correspondiente según el valor del parámetro "progreso" en los índices. C = no corregido, V = corregido, T = validado, E = problemática.
Por ejemplo, {{#invoke:Wikidata|badge|qid=Q30097675}} = corregida («Q30097675» corresponde al identificador de Lecciones Matemáticas).
Esta documentación está transcluida desde Módulo:Wikidata/doc.
Los editores pueden experimentar en la zona de pruebas
Por favor, añade las categorías a la subpágina de documentación.
(subpáginas - enlaces)

require('strict')
local p = {}
--------------------------------------------------------------------
-- A continuación, función p.claim y funciones locales necesarias --
-- Adaptado de https://ca.wikisource.org/wiki/Module:Wikidata     --
--------------------------------------------------------------------
local wiki = {
	langcode = mw.language.getContentLanguage().code
}

-- Table of language codes: requested or default and its fallbacks
local function findLang(langcode)
	if mw.language.isKnownLanguageTag(langcode or '') == false then
		local cframe = mw.getCurrentFrame()
		local pframe = cframe:getParent()
		langcode = pframe and pframe.args.lang
		if mw.language.isKnownLanguageTag(langcode or '') == false then
			if not mw.title.getCurrentTitle().isContentPage then
				langcode = cframe:preprocess('{{int:lang}}')
			end
			if mw.language.isKnownLanguageTag(langcode or '') == false then
				langcode = wiki.langcode
			end
		end
	end
	
	local languages = mw.language.getFallbacksFor(langcode)
	table.insert(languages, 1, langcode)
	if langcode == wiki.langcode then
		for _, l in ipairs({}) do
			table.insert(languages, l)
		end
	end
	
	return languages
end

-- Argument is 'set' when it exists (not nil) or when it is not an empty string.
local function isSet(var)
	return not (var == nil or (type(var) == 'string' and mw.text.trim(var) == ''))
end

-- get safely a serialized snak
local function getSnak(statement, snaks)
	local ret = statement
	for i, v in ipairs(snaks) do
		if not ret then return end
		ret = ret[v]
	end
	return ret
end

-- mw.wikibase.getLabelWithLang or getLabelByLang with a table of languages
local function getLabelByLangs(id, languages)
	local label
	local lang
	for _, l in ipairs(languages) do
		if l == wiki.langcode then
			-- using getLabelWithLang when possible instead of getLabelByLang
			label, l = mw.wikibase.getLabelWithLang(id)
		else
			label = mw.wikibase.getLabelByLang(id, l)
		end
		if label then
			lang = l
			break
		end
	end
	return label, lang
end

-- format data value wikibase-entityid: types wikibase-item, wikibase-property
function p.printDatatypeEntity(data, parameters)
	local entity_id = data['id']
	if parameters.formatting == 'raw' then
		return entity_id, entity_id
	end
	local label, _ = getLabelByLangs(entity_id, parameters.lang)
	local sitelink = mw.wikibase.getSitelink(entity_id)
	local labelcase = label or sitelink
	if parameters.citado and parameters.citado ~= '' then labelcase = parameters.citado end
	local entity_page = 'Special:EntityPage/' .. entity_id
	local ret1
	if parameters.formatting == 'label' then
		ret1 = labelcase or entity_id
	else
		if sitelink then
			ret1 = '[[' .. sitelink .. '|' .. labelcase .. ']]'
		elseif label and string.match(parameters.formatting or '', 'internallink$') and not mw.wikibase.getEntityIdForTitle(label) then
			ret1 = '[[' .. label .. '|' .. labelcase .. ']]'
		else	--si no existe la pág. en WS, crea enlace a WD
			ret1 = '[[d:' .. entity_page .. '|<span style="color:#5f9cbb;">' .. (labelcase or entity_id) .. '</span>]]'
		end
	end
	
	return ret1
end

local function getSnakValue(snak, parameters)
	if snak.snaktype == 'value' then
		-- see Special:ListDatatypes
		if snak.datatype == 'wikibase-item' or snak.datatype == 'wikibase-property' then
			return p.printDatatypeEntity(snak.datavalue.value, parameters)
		end
	elseif snak.snaktype == 'somevalue' then
		if parameters.referenced and parameters.referenced ~= '' then return parameters.referenced end
		if parameters.citado and parameters.citado ~= '' then return parameters.citado end
	end
	return mw.wikibase.renderSnak(snak)
end
local function orderedpairs(array, order)
	if not order then return pairs(array) end

	-- return iterator function
	local i = 0
	return function()
		i = i + 1
		if order[i] then
			return order[i], array[order[i]]
		end
	end
end
local function getCitadoValue(claim)
	local result = ""
	if claim.qualifiers then
		if claim.qualifiers['P1932'] then
			local wqualif = claim.qualifiers['P1932'][1].datavalue.value
			if wqualif and wqualif ~= '' then
				return wqualif
			end
		end
	end
	return result
end
local function getReferencedValue(claim, parameters, reftypes)
	local result = ""
	-- traverse through all references
	for ref in pairs(claim.references or {}) do
		local refparts
		
		-- traverse through all parts of the current reference
		for snakkey, snakval in orderedpairs(claim.references[ref].snaks or {}, claim.references[ref]["snaks-order"]) do
			for i, reftype in ipairs(reftypes) do
				if snakkey == reftype then
					if refparts then refparts = refparts .. ", " else refparts = "" end
					for snakidx = 1, #snakval do
						if snakidx > 1 then refparts = refparts .. ", " end
						refparts = refparts .. getSnakValue(snakval[snakidx], parameters)
					end
				end
			end
		end
		if refparts then result = result .. refparts end
	end
	return result
end

local function getQualifierSnak(claim, qualifierId, parameters)
	-- a "snak" is Wikidata terminology for a typed key/value pair
	-- a claim consists of a main snak holding the main information of this claim,
	-- as well as a list of attribute snaks and a list of references snaks
	if qualifierId then
		-- search the attribute snak with the given qualifier as key
		if claim.qualifiers then
			local qualifier = claim.qualifiers[qualifierId]
			if qualifier then
				if qualifier[1].datatype == "monolingualtext" then
					-- iterate over monolingualtext qualifiers to get local language
					for idx in pairs(qualifier) do
						if getSnak(qualifier[idx], {"datavalue", "value", "language"}) == parameters.lang[1] then
							return qualifier[idx]
						end
					end
				elseif parameters.list then
					return qualifier
				else
					return qualifier[1]
				end
			end
		end
		return nil, '<span class="error">No se encuentra el cualificador.</span>'
	else
		return claim.mainsnak
	end
end

local function getValueOfClaim(claim, qualifierId, parameters)
	local snak, error = getQualifierSnak(claim, qualifierId, parameters)
	local reftypes = {'P5997'} -- propiedades "tipo referencia" que pueden denotar un valor oculto

	parameters.referenced = getReferencedValue(claim, parameters, reftypes) 
	parameters.citado = getCitadoValue(claim)

	if not snak then
		return nil, nil, error
	elseif snak[1] then -- a multi qualifier
		local result = {}
		for idx in pairs(snak) do
			result[#result + 1] = getSnakValue(snak[idx], parameters)
		end
		return mw.text.listToText(result), nil
	else -- a property or a qualifier (lo habitual)
		return getSnakValue(snak, parameters)
	end
end

local function getEntityId(args, pargs, unnamed)
	pargs = pargs or {}
	local id = args.item or args.from or (unnamed and mw.text.trim(args[1] or '') or nil)
	if not isSet(id) then
		id = pargs.item or pargs.from or (unnamed and mw.text.trim(pargs[1] or '') or nil)
	end
	if not isSet(id) then
		id = mw.wikibase.getEntityIdForCurrentPage()
	end
	return id
end

local function getArg(value, default, aliases)
	if type(value) == 'boolean' then return value
	elseif value == "false" or value == "no" then return false
	elseif value == "true" or value == "yes" then return true
	elseif value and aliases and aliases[value] then return aliases[value]
	elseif isSet(value) then return value
	elseif default then return default
	else return nil
	end
end

-- Main function claim ---------------------------------------------
-- on debug console use: =p.claim{item="Q...", property="P...", ...}
function p.claim(frame)
	local args = frame.args or frame -- via invoke or require
	local pargs = frame.args and frame:getParent().args or {}

	-- arguments
	local parameters = {}
	parameters.id = getEntityId(args, pargs)
	if parameters.id == nil then return end
	parameters.property = string.upper(args.property or "")
	local qualifierId = {}
	qualifierId[1] = getArg(string.upper(args.qualifier or ""))
	local i = 2
	while isSet(args["qualifier" .. i]) do
		qualifierId[i] = string.upper(args["qualifier" .. i])
		i = i + 1
	end
	parameters.formatting = getArg(args.formatting)
	parameters.list = getArg(args.list, true, {firstrank='bestrank'})
	parameters.tabla = getArg(args.tabla)
	local default = args.default
	parameters.lang = findLang(args.lang)

	-- fetch property
	local claims = mw.wikibase.getBestStatements(parameters.id, parameters.property)
	if #claims == 0 then
		return default
	end
	
	-- defaults for table
	local preformat, postformat = "", ""
	-- get initial sort indices
	local sortindices = {}
	for idx in pairs(claims) do
		sortindices[#sortindices + 1] = idx
	end

	local result
	if parameters.tabla then
		local value
		result = {}
		local values = {}
		for idx in pairs(claims) do
			local claim = claims[sortindices[idx]]
			value = getValueOfClaim(claim, qualifierId[1], parameters)
			values[#values + 1] = {}
			if value then
				values[#values]["col0"] = value
				result[#values] = value
			end
		end
		return result
	elseif parameters.list then
		parameters.separator = mw.message.new('Comma-separator'):inLanguage(parameters.lang[1]):plain()
		parameters.conjunction = (mw.message.new('And'):inLanguage(parameters.lang[1]):plain() .. mw.message.new('Word-separator'):inLanguage(parameters.lang[1]):plain())
		-- iterate over all elements and return their value (if existing)
		local value
		result = {}
		local values = {}
		for idx in pairs(claims) do
			local claim = claims[sortindices[idx]]
			value = getValueOfClaim(claim, qualifierId[1], parameters)
			values[#values + 1] = {}
			if value then
				values[#values]["col0"] = value
				result[#values] = value
			end
		end
		result = preformat .. mw.text.listToText(result, parameters.separator, parameters.conjunction) .. postformat
	else
		-- return first element
		local claim = claims[sortindices[1]]
		result = getValueOfClaim(claim, qualifierId[1], parameters)
	end
	
	if not isSet(result) then
		result = default
	end
	return result or ''
end
--------------------------------------------------------------------------------
-- Get an Item based on what's passed in the 'wikidata' or 'page' parameters of
-- the args, or the current page's ID otherwise.
local function getItem( args )
	local id = nil
	-- If args is a table with an appropriate element, use it.
	if type( args ) == 'table' then
		if args.wikidata ~= '' and args.wikidata ~= nil then
			id = args.wikidata
		elseif args.wikidata_id ~= '' and args.wikidata_id ~= nil then
			id = args.wikidata_id
		elseif args.page ~= '' and args.page ~= nil then
			local title = mw.title.new( args.page )
			id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.text )
			-- If no entity for this page, maybe it's a subpage and we should look for the root page's entity.
			if id == nil then
				id = mw.wikibase.getEntityIdForTitle( title.nsText .. title.rootText )
			end
		end
	end
	if type( args ) == 'string' and args ~= '' then
		id = args
	end
	return mw.wikibase.getEntity( id )
end
--------------------------------------------------------------------------------
-- Exported method. Get wikitext for displaying an edition's badges from Wikidata.
-- Test: =p.badge({args={qid='Q30097675'}})
function p.badge( frame )
	local args = frame.args or frame -- via invoke or require
	local item = getItem( args )	--por defecto, id de la página
	
	local badges = {}
	
	if args.qid ~= nil then			--pero si pasamos un qid, id pasado
		item = mw.wikibase.getEntity(args.qid)
	end
	
	local status = args.ws
	
	-- status en el índice a badge
	if status == 'C' or status == 'P'  then
		status = "Q20748091"
	elseif status == 'V' then
		status = "Q20748092"
	elseif status == 'T' then
		status = "Q20748093"
	elseif status == 'E' or status == 'L' then
		status = "Q20748094"
	end

	if not ( item and item.sitelinks and item.sitelinks.eswikisource and #item.sitelinks.eswikisource.badges > 0)  and not (status) then
		return ''
	end
	
	-- alguno con más prioridad que el otro? TODO: hacer algo en caso de discrepancia
	if status then
		badges = {status}
	end
	if  ( item and item.sitelinks and item.sitelinks.eswikisource and #item.sitelinks.eswikisource.badges > 0) then
		badges = {unpack(badges), unpack(item.sitelinks.eswikisource.badges)}
	end
	-- raw = tabla con QID de las badges
	if args.raw then return badges end
	
	local out = ''
	for _, badge in pairs( badges ) do
		local badgeOut
		local badgeItem = mw.wikibase.getEntity( badge )
		local wikisourceBadgeClass = 'Q75042035'
		local badgeName = ''
		if badgeItem.claims.P31[1].mainsnak.datavalue.value.id == wikisourceBadgeClass and badgeItem.claims.P18 ~= nil then
			local imageName = badgeItem.claims.P18[1].mainsnak.datavalue.value
			if mw.wikibase.getLabel( badge ) ~= nil then
				badgeName = mw.wikibase.getLabel( badge )
			end
			-- TODO: Crear una página de ayuda apropiada para el nivel de los *textos*
			badgeOut = '<span class="indicator-badge">[[File:' .. imageName .. '|16px|link=Ayuda:Nivel de las páginas|' .. badgeName .. ']]</span>'
			if args.indicator then
				badgeOut = '<indicator name="wikisource-badge-' .. badgeName .. '">' .. badgeOut .. '</indicator>'
			end
			
			if args.category and badgeItem.claims.P910 ~= nil then
				local categoryQid = badgeItem.claims.P910[1].mainsnak.datavalue.value.id
				local category = mw.wikibase.getEntity( categoryQid )
				badgeOut = badgeOut .. '['..'[' .. category.sitelinks.eswikisource.title .. ']'..']' 
			end
			
			out = out .. badgeOut
		end
	end
	return mw.getCurrentFrame():preprocess(out)
end

return p