Zum Inhalt springen

„Modul:Wikibase“ – Versionsunterschied

aus AufEinWort, der freien Forschung
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
 
Zeile 93: Zeile 93:
if ok and type(desc) == 'string' and desc ~= '' then return desc end
if ok and type(desc) == 'string' and desc ~= '' then return desc end
return nil
return nil
end
-- Vollständige Entitäts-ID prüfen; konfigurierte lokale Namensräume verwenden.
function util.getEntityPageTarget(entityId, namespaces)
    local kind = type(entityId) == 'string' and entityId:match('^([QPL])[1-9]%d*$')
    if not kind then error('Wikibase: ungültige Entitäts-ID') end
    local namespace = namespaces and namespaces[kind]
    if type(namespace) ~= 'string' or util.trim(namespace) == '' then
        error('Wikibase/config: Namensraum für ' .. kind .. ' fehlt')
    end
    namespace = util.trim(namespace):gsub(':$', '')
    return namespace .. ':' .. entityId
end
end



Aktuelle Version vom 16. Oktober 2026, 09:28 Uhr

Die Dokumentation für dieses Modul kann unter Modul:Wikibase/Doku erstellt werden

local util = {}

local function trim(s)
	if type(s) ~= 'string' then return s end
	return (s:gsub('^%s+', ''):gsub('%s+$', ''))
end

util.trim = trim

function util.getArgs(frame)
	local args = {}
	if not frame then return args end
	for k, v in pairs(frame.args or {}) do
		if v ~= '' and v ~= nil then args[k] = v end
	end
	return args
end

function util.getEntityType(id)
	if type(id) ~= 'string' then return nil end
	if id:match('^Q%d+$') then return 'item' end
	if id:match('^P%d+$') then return 'property' end
	if id:match('^L%d+$') then return 'lexeme' end
	return nil
end

function util.detectEntityId(args)
	local ordered = {}
	local function push(v)
		if v ~= nil and v ~= '' then table.insert(ordered, v) end
	end
	push(args.L or args.lexeme or args.l)
	push(args.P or args.p)
	push(args.Q or args.q)
	push(args.entity or args.Entity)
	push(args.id or args.ID)
	push(args[1])

	for _, v in ipairs(ordered) do
		local s = trim(tostring(v))
		if s ~= '' then
			local id = s:match('^[QPL]%d+$')
			if not id then id = s:match('^.-:([QPL]%d+)$') end
			if id then return id end
		end
	end

	local ok, currentId = pcall(mw.wikibase.getEntityIdForCurrentPage)
	if ok and type(currentId) == 'string' and currentId:match('^[QPL]%d+$') then
		return currentId
	end
	return nil
end

function util.getContentLangCode()
	local code = 'de'
	if mw.getContentLanguage then
		local cl = mw.getContentLanguage()
		if cl and cl.getCode then
			code = cl:getCode()
		end
	end
	return code
end

function util.getEntityLabelOrLemma(entityId)
	if not entityId then return nil end
	local etype = util.getEntityType(entityId)

	if etype == 'lexeme' then
		local ok, entity = pcall(mw.wikibase.getEntity, entityId)
		if ok and type(entity) == 'table' and type(entity.lemmas) == 'table' then
			local lang = util.getContentLangCode()
			local l = entity.lemmas[lang]
			if l and type(l) == 'table' and l.value and l.value ~= '' then
				return l.value
			end
			for _, obj in pairs(entity.lemmas) do
				if type(obj) == 'table' and obj.value and obj.value ~= '' then
					return obj.value
				end
			end
		end
	end

	local ok, label = pcall(mw.wikibase.getLabel, entityId)
	if ok and type(label) == 'string' and label ~= '' then return label end
	return entityId
end

function util.getDescription(entityId)
	local ok, desc = pcall(mw.wikibase.getDescription, entityId)
	if ok and type(desc) == 'string' and desc ~= '' then return desc end
	return nil
end

-- Vollständige Entitäts-ID prüfen; konfigurierte lokale Namensräume verwenden.
function util.getEntityPageTarget(entityId, namespaces)
    local kind = type(entityId) == 'string' and entityId:match('^([QPL])[1-9]%d*$')
    if not kind then error('Wikibase: ungültige Entitäts-ID') end
    local namespace = namespaces and namespaces[kind]
    if type(namespace) ~= 'string' or util.trim(namespace) == '' then
        error('Wikibase/config: Namensraum für ' .. kind .. ' fehlt')
    end
    namespace = util.trim(namespace):gsub(':$', '')
    return namespace .. ':' .. entityId
end

function util.buildEntityLink(entityId, linkText, target)
    linkText = trim(tostring(linkText or '')):gsub('[\r\n]+', ' ')
    target = (target and tostring(target):lower()) or 'special'

    if target == 'ns' then
        local etype = util.getEntityType(entityId)
        local prefix =
            (etype == 'item' and 'Item:') or
            (etype == 'property' and 'Property:') or
            (etype == 'lexeme' and 'Lexeme:') or
            ''
        local text = (linkText ~= '' and linkText) or entityId
        return string.format('[[%s%s|%s]]', prefix, entityId, text)
    end

    -- Default: Special:EntityPage/...
    local text = (linkText ~= '' and linkText) or entityId
    return string.format('[[Special:EntityPage/%s|%s]]', entityId, text)
end

function util.setShortdesc(frame, text)
    if not frame then return '' end
    text = trim(tostring(text or '')):gsub('[\r\n]+', ' ')
    if text == '' then return '' end

    local ok, result = pcall(function()
        return frame:callParserFunction('SHORTDESC', text)
    end)
    if not ok then return '' end
    return result or ''
end

function util.smwAnnotate(kv)
  if type(kv) ~= 'table' then return '' end
  local out = {}
  for prop, val in pairs(kv) do
    prop = util.trim(tostring(prop or ''))
    val  = util.trim(tostring(val or '')):gsub('[\r\n]+', ' ')
    if prop ~= '' and val ~= '' then
      table.insert(out, string.format('[[%s::%s]]', prop, val))
    end
  end
  return table.concat(out, '')
end


-- Zusätzliche Q-Aussagen: getrennt von den bisherigen Helfern für P und L.
-- Alle Entitätszugriffe erfolgen über mw.wikibase, damit der Client ihre
-- Verwendung beim Parsen der Inhaltsseite erfassen kann.
function util.getClassificationName(id)
    if id:match('^L%d+$') then
        local entity = mw.wikibase.getEntity(id)
        local lemmas = entity and entity.lemmas or {}
        if lemmas.de and lemmas.de.value and lemmas.de.value ~= '' then
            return lemmas.de.value
        end
        local languages = {}
        for language in pairs(lemmas) do languages[#languages + 1] = language end
        table.sort(languages)
        for _, language in ipairs(languages) do
            local lemma = lemmas[language]
            if lemma.value and lemma.value ~= '' then return lemma.value end
        end
        return id
    end
    local label = mw.wikibase.getLabelByLang(id, 'de')
    return (label and label ~= '') and label or id
end

-- Nur verlustfrei behandelte Datentypen übernehmen. Komplexe Werte werden
-- mit Hinweis ausgelassen, statt unbemerkt Zeitpräzision/Einheiten zu verlieren.
function util.classificationValue(snak)
    if not snak or snak.snaktype ~= 'value' then return nil end
    local dv = snak.datavalue
    if not dv then return nil, 'Aussage ohne datavalue' end
    local value = dv.value
    if dv.type == 'wikibase-entityid' and type(value) == 'table' then
        local id = value.id
        if not id and value['numeric-id'] then
            local prefixes = { item = 'Q', property = 'P', lexeme = 'L' }
            local prefix = prefixes[value['entity-type']]
            if prefix then id = prefix .. tostring(value['numeric-id']) end
        end
        if id and id:match('^[QPL]%d+$') then
            return util.getClassificationName(id)
        end
        return nil, 'Nicht unterstützter Entitätsverweis'
    elseif dv.type == 'string' and type(value) == 'string' then
        return value
    elseif dv.type == 'monolingualtext' and type(value) == 'table' then
        return value.text
    end
    return nil, 'Nicht unterstützter Datentyp: ' .. tostring(snak.datatype or dv.type)
end

-- Q-Konfiguration: lokale Q-/P-ID -> deutsches Label; Klartext bleibt erlaubt.
-- Keine dauerhafte Zwischenspeicherung: Nutzung wird auf der Inhaltsseite erfasst.
function util.resolveSmwPropertyName(setting)
    local name = util.trim(tostring(setting or ''))
    if name:match('^[QP][1-9]%d*$') then
        return util.getClassificationName(name)
    end
    return name
end

function util.getConfiguredQStatements(entityId, config)
    local rows, notices, seenProperties = {}, {}, {}
    if not entityId or not entityId:match('^Q%d+$') then return rows, notices end
    for slot = 1, 6 do
        local property = util.trim(tostring(config['prop' .. slot] or ''))
        if property ~= '' then
            if not property:match('^P[1-9]%d*$') then
                notices[#notices + 1] = 'Wikibase/config: prop' .. slot ..
                    ' enthält keine gültige P-ID: ' .. property
            elseif not seenProperties[property] then
                seenProperties[property] = true
                -- BestStatements: bevorzugte, sonst normale; keine missbilligten.
                -- Auch leere Ergebnisse abfragen, damit spätere Aussagen erfasst werden.
                local statements = mw.wikibase.getBestStatements(entityId, property)
                local name = util.getClassificationName(property)
                local seenValues = {}
                for _, statement in ipairs(statements or {}) do
                    local value, warning = util.classificationValue(statement.mainsnak)
                    if warning then
                        notices[#notices + 1] = property .. ': ' .. warning
                    end
                    if value and value ~= '' and not seenValues[value] then
                        seenValues[value] = true
                        rows[#rows + 1] = { property = name, value = value }
                    end
                end
            end
        end
    end
    return rows, notices
end

-- Daten aus Labels/Werten dürfen keine zusätzliche Wikitext-Syntax erzeugen.
function util.smwLiteral(value)
    return mw.text.nowiki(tostring(value):gsub('[\r\n]+', ' '))
end

function util.smwAnnotateRows(rows)
    local out = {}
    for _, row in ipairs(rows) do
        -- :: ist die SMW-Trennsyntax; in einem Attributnamen nicht zulassen.
        if row.property:find('::', 1, true) then
            error('Wikibase: P-Label enthält die SMW-Trennsyntax "::": ' .. row.property)
        end
        out[#out + 1] = '[[' .. util.smwLiteral(row.property) .. '::' ..
            util.smwLiteral(row.value) .. '| ]]'
    end
    return table.concat(out)
end

-- Explizit während des Parsens speichern, unabhängig von sichtbarem Wikitext.
-- Je Wert ein Aufruf: wiederholte Attribute bleiben mehrwertig.
function util.setSmwRows(frame, rows)
    local output = {}
    for _, row in ipairs(rows or {}) do
        local property = util.trim(tostring(row.property or ''))
        local value = util.trim(tostring(row.value or ''))
        if property ~= '' and value ~= '' then
            if property:find('::', 1, true) or property:find('=', 1, true) then
                error('Wikibase: unzulässiger SMW-Attributname: ' .. property)
            end
            output[#output + 1] = frame:callParserFunction{
                name = '#set',
                args = { property .. '=' .. util.smwLiteral(value) }
            } or ''
        end
    end
    return table.concat(output)
end

return util