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