Módulo:Zona de pruebas/Miguillen/Wikidata

Este módulo no tiene página de documentación[crear]
--[[*********************************************************************************
    * 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: 6 de septiembre de 2014.
    *
    * Estado: En uso. 
    *
    *********************************************************************************`-- ]]
 
local p = {}
 
 --[[ =========================================================================
            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.",
        ["other entity"] = "Enlaces a elementos diferentes desabilitado."
    },
    ["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 ~= nil and id ~= ''  then
            return mw.wikibase.getEntityObject( id )
        else 
            return mw.wikibase.getEntityObject()
        end 
 
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 determinar el rango     
     ========================================================================= `-- ]]
function getRango(tablaDeclaraciones)
 
	local rank = 'deprecated'
 
    for indice, declaracion in pairs(tablaDeclaraciones) do
        if declaracion.rank == 'preferred' then
            return 'preferred'
        elseif declaracion.rank == 'normal' then
            rank = 'normal'
        end 
    end
 
    return rank
end
 
 --[[ =========================================================================
      Función para determinar la declaracion o declaraciones de mayor rango    
     ========================================================================= `-- ]]
function filtrarDeclaracionPorRango(tablaDeclaraciones)
    local rango = getRango(tablaDeclaraciones)
    local tablaAuxiliar = tablaDeclaraciones
    tablaDeclaraciones = {}
 
    for indice, declaracion in pairs(tablaAuxiliar) do
        if declaracion.rank == rango then
            table.insert(tablaDeclaraciones, declaracion)
        end 
    end 
    return tablaDeclaraciones
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[mw.ustring.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 las declaraciones      
     ========================================================================= `-- ]] 
 
function p.getDeclaraciones(entityId)
	
 
    -- == Comprobamos que existe un ítem enlazado a la página en Wikidata ==
    if pcall (SelecionEntidadPorId, entityId ) == false then 
    	return false
    end
    local entidad  = SelecionEntidadPorId(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)  then
        return '' -- Si el ítem no tiene declaraciones no devuelve nada
    end
    -- == Declaración de formato y concatenado limpio ==
 
    return entidad.claims
end

 --[[ =========================================================================
      Función para  crear la cadena que devolverá la declaración     
     ========================================================================= `-- ]] 
     
function p.getPropiedad(opciones, declaracion)
	local propiedad = {}
	local tablaOrdenada = {}
    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
    
    if declaracion ~= nil then
        tablaOrdenada = declaracion
    elseif p.getDeclaraciones(opciones.entityId) == false then
    	return formatoError( 'other entity' )
    elseif p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)] ~= nil then 
    	tablaOrdenada = p.getDeclaraciones(opciones.entityId)[mw.ustring.upper(propiedad)]
    	
    else
    	return ''
    end
    
    -- == Si solo se desea que devuelva un valor ==
    if opciones.uno == 'sí' then -- Para que devuelva el valor de índice 1
        return formatoDeclaracion( tablaOrdenada[1],opciones)
    end
    if (opciones.rangoMayor == 'sí') then -- Para que devuelva los valores de mayor rango
        tablaOrdenada = filtrarDeclaracionPorRango(tablaOrdenada)
 
    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 (snaktype)
        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'] and opciones['valor-módulo'] ~= "" ) or (opciones['value-function'] and opciones['valor-function'] ~= "" ) then
        if not opciones['valor-módulo'] or not opciones['valor-función'] then
            return formatoError( 'unknown-value-module' )
        end
        local formateado = require ('Módulo:' .. 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 == 'url' then     --Tipo URL (dirección web)
		return value.url
    elseif valorDato.type == 'time' then                 -- Tipo: Fecha/hora
        return require('Módulo:Wikidata/Fecha').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
    	local globo = require('Módulo:Wikidata/Globos')[valorDato.value.globe]
 
--Concatenamos los valores de latitud y longitud dentro de la plantilla Coord
 
        if globo ~= 'earth' then
            return  marco:preprocess('{{coord|' .. valorDato.value['latitude'] .. '|' .. 
                   valorDato.value['longitude'] .. '|globe:' .. globo .. '_type:' .. opciones.tipo .. '|display=' .. 
                   opciones.display ..'|formato=' .. opciones.formato..'}}')
        else
        	return  marco:preprocess('{{coord|' .. valorDato.value['latitude'] .. '|' .. 
                   valorDato.value['longitude'] .. '|type:' .. opciones.tipo .. '|display=' .. 
                   opciones.display ..'|formato=' .. opciones.formato..'}}')
        end
 
    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 principal     
     ========================================================================= `-- ]]
 
function p.Wikidata( frame )
    marco = frame
    local args = frame.args
    local valorWikidata = p.getPropiedad( frame.args , nil)
 
    if args.prioridad == 'sí' and valorWikidata  ~= '' then -- Si se da el valor sí a prioridad tendrá preferencia el valor de                                                                             Wikidata 
        return valorWikidata -- valor que sustituye al valor de Wikidata parámetro 2
    elseif args.valor ~= nil and args.valor ~= '' then 
         return args.valor
    else
        return valorWikidata
  end  
end
 
return p