Zum Inhalt springen

Modul:NormdatenWikidataExtern

aus AufEinWort, der freien Forschung
Vorlagenprogrammierung Diskussionen Lua Unterseiten
Modul Deutsch

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


-- Externer Normdatenvergleich fuer UnlinkedWikibase 3.0.0.
-- Keine Verwendung von mw.wikibase oder lokalen Q-/P-Kennungen.
local p = {}

local function trim(value)
    return mw.text.trim(tostring(value or ''))
end

local function notice(message)
    return tostring(mw.html.create('div')
        :addClass('normdaten-wikidata-hinweis')
        :wikitext('Normdatenabgleich mit Wikidata: ' .. message))
end

-- Wie bei Best-Rank-Abfragen: bevorzugte Aussagen vor normalen;
-- veraltete Aussagen werden nicht verwendet. Unbekannte Werte und
-- unerwartete Daten werden nicht als nachgewiesenes Fehlen behandelt.
local function valuesFor(entity, property)
    local claims = entity.claims[property]
    if claims == nil then
        return {}, 'missing'
    end
    if type(claims) ~= 'table' then
        return {}, 'unknown'
    end
    local preferred = false
    for _, claim in ipairs(claims) do
        if type(claim) ~= 'table' then
            return {}, 'unknown'
        end
        if claim.rank == 'preferred' then
            preferred = true
        end
    end
    local values, unknown = {}, false
    for _, claim in ipairs(claims) do
        local selected = claim.rank == 'preferred'
            or (not preferred and claim.rank == 'normal')
        if selected then
            local snak = claim.mainsnak
            if type(snak) ~= 'table' then
                unknown = true
            elseif snak.snaktype == 'value' then
                local data = snak.datavalue
                if type(data) == 'table' and type(data.value) == 'string'
                    and trim(data.value) ~= '' then
                    values[trim(data.value)] = true
                else
                    unknown = true
                end
            elseif snak.snaktype ~= 'novalue' then
                unknown = true
            end
        elseif claim.rank ~= 'deprecated' and claim.rank ~= 'normal' then
            unknown = true
        end
    end
    if unknown then
        return values, 'unknown'
    elseif next(values) then
        return values, 'present'
    end
    return values, 'missing'
end

function p.check(frame)
    local args = frame.args
    if trim(args.TYP) ~= 'p' then
        return ''
    end
    local api = mw.ext and mw.ext.UnlinkedWikibase
    if not api or type(api.getEntity) ~= 'function'
        or type(api.getEntityIdForCurrentPage) ~= 'function' then
        return notice('UnlinkedWikibase ist nicht verfügbar.')
    end
    local ok, id = pcall(api.getEntityIdForCurrentPage)
    if not ok then
        return notice('Die externe Objektzuordnung konnte nicht gelesen werden.')
    end
    if type(id) ~= 'string' or not id:match('^Q%d+$') then
        return notice('Keine externe Wikidata-ID zugeordnet; Vergleich nicht ausgeführt.')
    end
    local loaded, entity = pcall(api.getEntity, id)
    if not loaded or type(entity) ~= 'table' or type(entity.claims) ~= 'table' then
        return notice('Daten für ' .. id
            .. ' noch nicht verfügbar oder Abruf fehlgeschlagen; Vergleich nicht ausgeführt.')
    end

    local categories, uncertain = {}, {}
    local properties = {
        { 'GND', 'P227' },
        { 'LCCN', 'P244' },
        { 'VIAF', 'P214' }
    }
    for _, spec in ipairs(properties) do
        local name, property = spec[1], spec[2]
        local localValue = trim(args[name])
        local remote, state = valuesFor(entity, property)
        local category
        if state == 'unknown' then
            uncertain[#uncertain + 1] = name
        elseif localValue == '' and state == 'present' then
            category = name .. ' in Wikipedia fehlt, in Wikidata vorhanden'
        elseif localValue ~= '' and state == 'missing' then
            category = name .. ' in Wikipedia vorhanden, fehlt jedoch in Wikidata'
        elseif name == 'GND' and localValue ~= '' and not remote[localValue] then
            category = 'GND in Wikipedia weicht von GND in Wikidata ab'
        end
        if category then
            categories[#categories + 1] = '[[Kategorie:Wikipedia:' .. category .. ']]'
        end
    end
    local result = table.concat(categories)
    if #uncertain > 0 then
        result = result .. notice('Keine eindeutige Auswertung für '
            .. table.concat(uncertain, ', ') .. ' in ' .. id .. '.')
    end
    return result
end

return p