Módulo:Wikidata
Apariencia
La documentación para este módulo puede ser creada en Módulo:Wikidata/doc
--[[*********************************************************************************
* Nombre: Módulo:Wikidata
*
* Descripción: Este módulo devuelve el valor o valores con o sin formato específico
* a una propiedad de Wikidata.
*
* Fecha última revisión: 4 de febrero de 2014.
*
* Estado: En uso.
*
*********************************************************************************`-- ]]
local p = {}
local Fechas = require( 'Módulo:Fechas')
--[[ =========================================================================
Mensajes de error
========================================================================= `-- ]]
local avisos = {
["errores"] = {
["property-param-not-provided"] = "Parámetro de la propiedad no proporcionado.",
["entity-not-found"] = "Entrada no encontrada.",
["unknown-claim-type"] = "Tipo de notificación desconocida.",
["unknown-snak-type"] = "Tipo de dato desconocido.",
["unknown-datavalue-type"] = "Tipo de dato desconocido.",
["unknown-entity-type"] = "Tipo de entrada desconocido.",
["unknown-value-module"] = "Debe ajustar ambos parámetros de valor y el valor del módulo de funciones.",
["value-module-not-found"] = "No se ha encontrado el módulo apuntado por valor-módulo.",
["value-function-not-found"] = "No se ha encontrado la función apuntada por valor-función."
},
["somevalue"] = "''valor desconocido''",
["novalue"] = "''sin valor''"
}
--[[ =========================================================================
Función para identificar el ítem correspondiente a la página o otro dado.
Esto último aún no funciona.
========================================================================= `-- ]]
function SelecionEntidadPorId( id )
if id then
return mw.wikibase.getEntityObject( id )
end
return mw.wikibase.getEntityObject()
end
--[[ =========================================================================
Función que identifica si el valor devuelto es un ítem o una propiedad
y en función de eso añade el prefijo correspondiente
========================================================================= `-- ]]
function SelecionEntidadPorValor( valor )
local prefijo = ''
if valor['entity-type'] == 'item' then
prefijo = 'Q' -- Prefijo de ítem
elseif valor['entity-type'] == 'property' then
prefijo = 'P' -- Prefijo de propiedad
else
return formatoError( 'unknown-entity-type' )
end
return prefijo .. valor['numeric-id'] -- Se concatena el prefijo y el código numérico
end
--[[ =========================================================================
Función auxiliar para dar formato a los mensajes de error
========================================================================= `-- ]]
function formatoError( clave )
return '<span class="error">' .. avisos.errores[clave] .. '</span>'
end
--[[ =========================================================================
Función para seleccionar el tipo de declaración: Referencia, valor principal
o calificador
========================================================================= `-- ]]
function seleccionDeclaracion(declaracion, opciones)
local fuente = {}
local propiedadFuente = {}
local calificador = opciones.calificador
if calificador ~= '' and declaracion['qualifiers'] ~= nil then
return declaracion.qualifiers[string.upper(calificador)][1] -- devuelve el calificador (solo devolverá el primer valor)
elseif opciones.dato == 'fuente' and declaracion['references'] ~= nil then
fuente = declaracion.references[1]['snaks']
for k,v in pairs(fuente) do
propiedadFuente = k
end
return declaracion.references[1]['snaks'][propiedadFuente][1] -- devuelve la fuente (queda que se itinere la tabla)
elseif calificador == '' and opciones.dato ~= 'fuente' then
return declaracion.mainsnak -- devuelve el valor principal
else
return ''
end
end
--[[ =========================================================================
Función para recopilar los valores de las declaraciones y crear la cadena que devolverá
========================================================================= `-- ]]
function formatoDeclaraciones(opciones)
if opciones.propiedad == 'precisión' or opciones.propiedad == 'latitud' or opciones.propiedad == 'longitud' then
propiedad = 'P625' -- Si damos el valor latitud, longitud o precisión equivaldrá a dar p625
else
propiedad = opciones.propiedad -- En el resto de casos se lee lo dado
end
if not propiedad then -- Comprobamos si existe la propiedad dada y en caso contrario se devuelve un error
return formatoError( 'property-param-not-provided' )
end
-- == Comprobamos que existe un ítem enlazado a la página en Wikidata ==
local entidad = SelecionEntidadPorId( opciones.entityId )
if not entidad then
return '' -- Si la página no está enlazada a un ítem no devuelve nada
end
-- == Comprobamos que el ítem tiene declaraciones (claims) ==
if (entidad.claims == nil) or (not entidad.claims[string.upper(propiedad)]) then
return '' -- Si no hay declaraciones no devuelve nada
end
-- == Declaración de formato y concatenado limpio ==
local propiedad = {}
if opciones.propiedad == 'latitud' or opciones.propiedad == 'longitud' or opciones.propiedad == 'precisión' then
propiedad = 'P625' -- Si damos el valor latitud, longitud o precisión equivaldrá a dar p625
else
propiedad = opciones.propiedad -- En el resto de casos se estima la propiedad dada
end
local tablaInicial = entidad.claims[string.upper(propiedad)]
-- == Si solo se desea que devuelva un valor ==
if opciones.uno == 'sí' then
return formatoDeclaracion( tablaInicial[1],opciones)
end
-- == Hacemos que índice de la declaracion 0 pase a ser 1. Necesario para que todo quede en el mismo orden que en el ítem ==
-- Para ello traspasamos tablaInicial a tablaOrdenada
local tablaOrdenada = {}
for indice, declaracion in pairs(tablaInicial) do
tablaOrdenada[indice+1] = declaracion
end
-- == Creamos una tabla (array) con los valores que devolverá ==
local formatoDeclaraciones = {}
for indice, declaracion in pairs(tablaOrdenada) do
table.insert( formatoDeclaraciones, formatoDeclaracion( declaracion, opciones ) )
end
return mw.text.listToText( formatoDeclaraciones, opciones['separador'], opciones['conjunción'] )
end
--[[ =========================================================================
Función que comprueba si la página está enlazada a Wikidata
en caso de estarlo pasa el valor como a argumento a la función formatSnak()
========================================================================= `-- ]]
function formatoDeclaracion( declaracion, opciones )
if not declaracion.type or declaracion.type ~= 'statement' then -- Se comprueba que tiene valor de tipo y que este sea statement (declaración) lo cual pasa siempre que existe la propiedad
return formatoError( 'unknown-claim-type' ) -- Si no se cumple devuelve error
end
return formatoDato(seleccionDeclaracion(declaracion, opciones), opciones)
--Pasamos el valor de la propiedad (mainsnak) a la función formatoDato()
end
--[[ =========================================================================
Función que comprueba el tipo de dato (snak)
si es value pasa el valor como argumento a la función formatoValorDato()
========================================================================= `-- ]]
function formatoDato( dato, opciones)
if dato.snaktype == 'somevalue' then
return avisos['somevalue'] -- Valor desconocido
elseif dato.snaktype == 'novalue' then
return avisos['novalue'] -- Sin valor
elseif dato.snaktype == 'value' then
return formatoValorDato( dato.datavalue, opciones) -- Si tiene el tipo de dato se pasa el valor a la función formatDatavalue()
else
return formatoError( 'unknown-snak-type' ) -- Tipo de dato desconocido
end
end
--[[ =========================================================================
Función que establece el tipo de formato en función del tipo de valor
(valorDato.type) y en caso de solicitarse un formato complemetario asocia
el módulo donde se establece el formato y la función de este que lo establece
========================================================================= `-- ]]
function formatoValorDato( valorDato, opciones)
-- == Si se da el parámetro valor-módulo y valor-función ==
if opciones['valor-módulo'] or opciones['value-function'] then
if not opciones['valor-módulo'] or not opciones['valor-función'] then
return formatoError( 'unknown-value-module' )
end
local formateado = require ('Module:' .. opciones['valor-módulo'])
if formateado == nil then
return formatoError( 'value-module-not-found' )
end
local fun = formateado[opciones['valor-función']]
if fun == nil then
return formatoError( 'value-function-not-found' )
end
return fun( valorDato.value, opciones)
end
-- == Formatos por defecto en función del tipo de valor ==
-- * Para tipo coordenadas cuando se da como valor de propiedad: latitud, longitud o precisión
if opciones.propiedad == 'latitud' then
return valorDato.value['latitude']
elseif opciones.propiedad == 'longitud' then
return valorDato.value['longitude']
elseif opciones.propiedad == 'precisión' then
return valorDato.value['precision']
-- * Con el resto de valores en propiedad
elseif valorDato.type == 'wikibase-entityid' then -- Tipo: Número de entidad que puede ser un ítem o propiedad
return formatoIdEntidad( SelecionEntidadPorValor( valorDato.value ), opciones)
elseif valorDato.type == 'string' then -- Tipo: Cadena de texto (string)
return valorDato.value
elseif valorDato.type == 'time' then -- Tipo: Fecha/hora
return FormateaFechaHora(valorDato.value,opciones)
elseif valorDato.type == 'quantity' then -- Tipo: Cantidad
--return mw.ustring.gsub(valorDato.value['amount'], '+','').. '±' .. valorDato.value['unit']
return valorDato.value['amount']
elseif valorDato.value['latitude'] and valorDato.value['longitude'] then -- Tipo: Coordenadas
--Concatenamos los valores de latitud y longitud dentro de la plantilla Coord
return marco:preprocess('{{coord|' .. valorDato.value['latitude'] .. '|' ..
valorDato.value['longitude'] .. '|globe:' .. opciones.cuerpo .. '_type:' .. opciones.tipo .. '|display=' ..
opciones.display ..'|formato=' .. opciones.formato..'}}')
else
return formatoError( 'unknown-datavalue-type' ) -- Si no es de ninguno de estos tipos devolverá error valor desconocido
end
end
--[[ =========================================================================
Damos formato a los enlaces internos
========================================================================= `-- ]]
function formatoIdEntidad(idEntidad, opciones)
local etiqueta = mw.wikibase.label( idEntidad )
local enlace = mw.wikibase.sitelink( idEntidad )
-- == Casos en los que existe enlace y no se da el valor no al parámetro enlace ==
if enlace and opciones['enlace'] ~= 'no' then -- Si existe la etiqueta y no se da valor el valor no al parametro enlace
if etiqueta then -- Si en Wikidata está definida una etiqueta para el idioma español
return '[[' .. enlace .. '|' .. etiqueta .. ']]' -- Devuelve la etiqueta como título del enlace
else
return '[[' .. enlace .. ']]' -- Devuelve solo el enlace
end
-- == Casos en los que no existe enlace o se da el valor no al parámetro enlace ==
elseif etiqueta then -- Si en Wikidata está definida una etiqueta para el idioma español
return etiqueta -- Devuelve solo la etiqueta
else
return '' -- Si no no devuelve nada
end
end
--[[ =========================================================================
Función para dar formato a fechas y horas
========================================================================= `-- ]]
function FormateaFechaHora(fechahora, opciones)
local etiqueta = fechahora.label
local timestamp = fechahora.time
local precision = fechahora.precision
if precision == 11 or -- Fecha de la que se conoce el año, el mes y el día
precision == 10 or -- Fecha de la que se conoce el año y el mes
precision == 9 then -- Fecha de la que se conoce el año
local dia, mes, anyo, calendario
if precision >= 11 then
dia = string.sub(timestamp, 17, 18)
end
if precision >= 10 then
mes = string.sub(timestamp, 14, 15)
end
anyo = string.sub(timestamp, 9, 12)
-- Corregir el año. En Wikidata el 1 a. C. está grabado como año 0000, el 2 a. C.
-- como 0001 (junto al signo '-'), etc.
if string.sub(timestamp,1,1) == '-' or anyo == '0000' then
anyo = '-' .. tostring(tonumber(anyo) + 1)
end
if fechahora.calendarmodel == 'http://www.wikidata.org/entity/Q1985786' then
calendario = 'juliano'
else
calendario = 'gragoriano'
end
return Fechas.Fecha({dia,mes,anyo;enlace=opciones.enlace;calendario=calendario})
elseif precision == 8 then -- Fecha de la que se conoce la década
return formatoError( 'unknown-datavalue-type' )
elseif precision == 7 then -- Fecha de la que se conoce el siglo
return formatoError( 'unknown-datavalue-type' )
elseif precision == 6 then -- Fecha de la que se conoce el milenio
return formatoError( 'unknown-datavalue-type' )
elseif precision == 3 then -- Fecha de la que se conoce el milenio
return anno
else
return formatoError( 'unknown-datavalue-type' )
end
end
--[[ =========================================================================
Función principal
========================================================================= `-- ]]
function p.Wikidata( frame )
marco = frame
local args = frame.args
local valorWikidata = formatoDeclaraciones( frame.args )
if args.prioridad == 'sí' and valorWikidata ~= '' then -- Si se da el valor sí a prioridad tendrá preferencia el valor de Wikidata
return formatoDeclaraciones( frame.args ) -- valor que sustituye al valor de Wikidata parámetro 2
elseif args.valor and args.valor ~= '' then
return args.valor
else
return formatoDeclaraciones( frame.args )
end
end
return p