Modul:WikidataIB
Dokumentasjon for denne modulen kan opprettes på Modul:WikidataIB/dok
local p = {} local rankOrder = { ['truth'] = 1, ['preferred'] = 2, ['normal'] = 3, ['deprecated'] = 4 } local i18n = { ['wikidata-linkback-edit'] = 'Redigere på Wikidata', ['wiki-article-not-available'] = 'Artikkelen er ikke tilgjengelig på denne wikien ennå', ['wikidata-more-results-exists'] = 'Flere verdier er tilgjengelige på wikidata', ['standard-timeformat'] = 'j. F Y', ['argument-property'] = 'property', ['argument-list'] = 'liste', ['argument-date'] = 'dato', ['argument-value'] = 'verdi', ['argument-label'] = 'pnavn', ['argument-noedit'] = 'noedit', ['argument-fallback'] = 'fallback', ['argument-suffix'] = 'suffiks', ['argument-suffix-label'] = 'suffiksnavn', ['argument-bounds'] = 'usikkerhet', ['category-rowproperty-no-arguments'] = '[[Kategori:Artikler med invoke WikidataIB rowProperty uten argumenter]]', ['category-getpropertyvalue-no-arguments'] = '[[Kategori:Artikler med invoke WikidataIB getPropertyValue uten argumenter]]', ['category-getpropertylabel-no-arguments'] = '[[Kategori:Artikler med invoke WikidataIB getPropertyLabel uten argumenter]]' } local arguments = { property = nil, list = nil, date = nil, wiki_value = nil, edit = nil, fallback = nil, usesuffix = nil, suffix_from_wiki = nil, label = nil, usebounds = nil, } local function dump(obj) return "<pre>" .. mw.dumpObject(obj) .. "</pre>" end local function getArgument(frame, argument) local args = frame.args if args[1] == nil then local pFrame = frame:getParent(); args = pFrame.args; for k,v in pairs( frame.args ) do args[k] = v; end end if args[argument] then return args[argument] end return nil end local function getArguments(frame) arguments.property = getArgument(frame, i18n['argument-property']) if not arguments.property then -- No such argument, try getting it as the first argument arguments.property = getArgument(frame, '1') end arguments.list = getArgument(frame, i18n['argument-list']) if arguments.list and arguments.list ~= "" and tonumber(arguments.list) ~= 0 then arguments.list = tonumber(arguments.list) else arguments.list = nil end arguments.date = getArgument(frame, i18n['argument-date']) arguments.wiki_value = getArgument(frame, i18n['argument-value']) arguments.edit = getArgument(frame, i18n['argument-edit']) if arguments.edit and arguments.edit == "1" and not arguments.wiki_value then arguments.edit = false else arguments.edit = true end arguments.fallback = getArgument(frame, i18n['argument-fallback']) if arguments.fallback and arguments.fallback ~= "" then arguments.fallback = true else arguments.fallback = false end arguments.usesuffix = getArgument(frame, i18n['argument-suffix']) arguments.suffix_from_wiki = getArgument(frame, i18n['argument-suffix-label']) arguments.label = getArgument(frame, i18n['argument-label']) arguments.usebounds = getArgument(frame, i18n['argument-bounds']) end local function getDate(qualifiers, dateformat, langcode) local out = nil if qualifiers then local qualifierID = "" if qualifiers['P585'] then qualifierID='P585' -- point-in-time elseif qualifiers['P580'] then qualifierID='P580' end -- from -- todo: timespans? P582 for k, v in pairs(qualifiers[qualifierID]) do if v.snaktype == 'value' then out = "(" .. mw.language.new(langcode):formatDate(dateformat, v.datavalue.value.time) .. ")" end end end return out end local function getOrder(qualifiers) local out = nil if qualifiers then local qualifierID = "P1545" -- sorting order / rank / series ordinal if qualifiers[qualifierID] then for k, v in pairs(qualifiers[qualifierID]) do if v.snaktype == 'value' then out = v.datavalue.value end end end end return out end local function sortTableRankAndOrder(t, order_descending) local retval = {} local function compare(a, b) if (a.rank and b.rank and rankOrder[a.rank] < rankOrder[b.rank]) then return true end if (a.rank and b.rank and rankOrder[a.rank] == rankOrder[b.rank]) and (a.order and b.order and ((order_descending and a.order < b.order) or (not order_descending and a.order > b.order))) then return true else return false end end table.sort(t, compare) end local function compareRank(oldrank, newrank) if (newrank and not oldrank) or (oldrank and newrank and rankOrder[newrank] < rankOrder[oldrank]) then return newrank else return oldrank end end local function getQValueLink(qvalue, fallback, fallbacklang, label_from_wiki) local sitelink = mw.wikibase.sitelink(qvalue) local label = label_from_wiki if not label then label = mw.wikibase.label(qvalue) end out = nil if qvalue then if label == nil then -- let's try the fallback-languages local checkQ = mw.wikibase.getEntityObject(qvalue) if checkQ then local i = 0 while i < #fallbacklang do i = i + 1 label = checkQ:getLabel( fallbacklang[i] ) if label ~= nil then break end end end if label == nil then -- no such luck, fall back to Q-values label = qvalue end end if sitelink and sitelink ~= label then out = "[[" .. sitelink .. "|" .. label .. "]]" elseif sitelink then out = "[[" .. sitelink .. "]]" else if fallback then out = "[[:d:Q" .. qvalue .. "|" .. label .. "]]<abbr title='" .. i18n['wiki-article-not-available'] .. "'>[*]</abbr>" else out = label end end end return out end local function roundToDecimalNum(number, decimalPlace) local mult = 10^(decimalPlace or 0) return math.floor(number * mult + 0.5) / mult end function RoundNumber(num, idp) end local function findNumberOfDecimals(number) -- first, let's make it a string local numStr = tostring(tonumber(number)) -- now let's get the decimals local integers,decimals = numStr:match('(%d+)%.(%d+)') return #decimals end -- This is used to get a value -- if the boolean "list" is set, it will concatenate all available values in a comma-separated list -- if "dateformat" is set, it will look for qualifier-dates (P585, P580) and include in parathensis and format accordingly to the dateformat local function getValue(propertyID, list, dateformat, edit, fallback, usesuffix, suffix_label, usebounds, value_from_wiki) if value_from_wiki and #value_from_wiki and value_from_wiki ~= "" then return value_from_wiki else local lang = mw.language.getContentLanguage() local fallbacklang = mw.language.getFallbacksFor( lang.code ) local entity = mw.wikibase.getEntityObject() local claims if entity and entity.claims then claims = entity.claims[propertyID] end local out = {} local highestrank = nil if claims then if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then -- if wiki-linked value output as link if possible for k, v in pairs(claims) do if v.rank ~= mw.wikibase.entity.claimRanks.RANK_DEPRECATED then out[#out + 1] = { output = getQValueLink("Q" .. v.mainsnak.datavalue.value["numeric-id"], fallback, fallbacklang) } -- now let's check for a suffix if usesuffix and v.mainsnak.datavalue.value.unit then -- find Q-value local qval = "" _, _, qval = string.find(v.mainsnak.datavalue.value.unit, "^https*://www.wikidata.org/entity/(Q%d+)$") if qval and qval ~= "" then local suffix = getQValueLink(qval, fallback, fallbacklang, suffix_label) if suffix then out[#out].output = out[#out].output .. " " .. suffix end end end if dateformat then local date = getDate(v.qualifiers, dateformat, lang.code) if date then out[#out].output = out[#out].output .. " " .. date end end out[#out].rank = v.rank out[#out].order = getOrder(v.qualifiers) highestrank = compareRank(highestrank, v.rank) end end elseif (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == 'quantity') then -- this is a quantity, output as value for k, v in pairs(claims) do if v.rank ~= mw.wikibase.entity.claimRanks.RANK_DEPRECATED then if v.mainsnak.datavalue.value['amount'] then out[#out + 1] = { output = lang:formatNum(tonumber(v.mainsnak.datavalue.value['amount'])) } end -- check for bounds if usebounds and v.mainsnak.datavalue.value['lowerBound'] and v.mainsnak.datavalue.value['upperBound'] then local lowdiff = tonumber(v.mainsnak.datavalue.value['amount']) - tonumber(v.mainsnak.datavalue.value['lowerBound']) local upperdiff = tonumber(v.mainsnak.datavalue.value['upperBound']) - tonumber(v.mainsnak.datavalue.value['amount']) local numDec = findNumberOfDecimals(v.mainsnak.datavalue.value['amount']) out[#out].output = out[#out].output .. " ±" .. tostring(roundToDecimalNum(lowdiff, numDec)) end -- now let's check for a suffix if usesuffix and v.mainsnak.datavalue.value.unit then -- find Q-value local qval = "" _, _, qval = string.find(v.mainsnak.datavalue.value.unit, "^https*://www.wikidata.org/entity/(Q%d+)$") if qval and qval ~= "" then local suffix = getQValueLink(qval, fallback, fallbacklang, suffix_label) if suffix then out[#out].output = out[#out].output .. " " .. suffix end end end if dateformat then local date = getDate(v.qualifiers, dateformat, lang.code) if date then out[#out].output = out[#out].output .. " " .. date end end out[#out].rank = v.rank out[#out].order = getOrder(v.qualifiers) highestrank = compareRank(highestrank, v.rank) end end elseif (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == 'time') then -- this is a quantity, output as value for k, v in pairs(claims) do if v.rank ~= mw.wikibase.entity.claimRanks.RANK_DEPRECATED then if v.mainsnak.datavalue.value['time'] then local timeformat = dateformat if not timeformat or timeformat == "" then timeformat = i18n['standard-timeformat'] end out[#out + 1] = { output = mw.language.new(lang.code):formatDate(timeformat, v.mainsnak.datavalue.value.time) } end -- now let's check for a suffix if usesuffix and v.mainsnak.datavalue.value.unit then -- find Q-value local qval = "" _, _, qval = string.find(v.mainsnak.datavalue.value.unit, "^https*://www.wikidata.org/entity/(Q%d+)$") if qval and qval ~= "" then local suffix = getQValueLink(qval, fallback, fallbacklang, suffix_label) if suffix then out[#out].output = out[#out].output .. " " .. suffix end end end if dateformat then local date = getDate(v.qualifiers, dateformat, lang.code) if date then out[#out].output = out[#out].output .. " " .. date end end out[#out].rank = v.rank out[#out].order = getOrder(v.qualifiers) highestrank = compareRank(highestrank, v.rank) end end elseif (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == 'string') then -- this is a string for k, v in pairs(claims) do if v.rank ~= mw.wikibase.entity.claimRanks.RANK_DEPRECATED then if v.mainsnak.datavalue.value then out[#out + 1] = { output = v.mainsnak.datavalue.value } end if dateformat then local date = getDate(v.qualifiers, dateformat, lang.code) if date then out[#out].output = out[#out].output .. " " .. date end end out[#out].rank = v.rank out[#out].order = getOrder(v.qualifiers) highestrank = compareRank(highestrank, v.rank) end end else -- Unknown type out[#out + 1] = { output = 'unknown type ' .. claims[1].mainsnak.datavalue.type } end end -- Now we'll have to sort the table according to rank and order sortTableRankAndOrder(out) -- Now we'll make the output local i = 0 local ret = {} while i < #out do i = i + 1 -- check if the rank is within the highestrank if out[i].rank == highestrank then if list then list = list - 1 end ret[#ret + 1] = out[i].output if not list or list < 0 then if i < #out then -- We still have entries, show it ret[#ret + 1] = '<abbr title="' .. i18n['wikidata-more-results-exists'] .. '>…</abbr>' break end end end end return table.concat(ret, ", ") end end -- This is used to get the name of the property with upper first case local function getProperty(propertyID, propertyname_from_wiki) if propertyname_from_wiki and #propertyname_from_wiki then return propertyname_from_wiki else local lang = mw.language.getContentLanguage() local out = mw.wikibase.label(propertyID) return lang:ucfirst(out) end end -- This is used to get the type of the property local function getUnitType(propertyID, value_from_wiki) if value_from_wiki and #value_from_wiki and value_from_wiki ~= "" then return value_from_wiki else local lang = mw.language.getContentLanguage() local fallbacklang = mw.language.getFallbacksFor( lang.code ) local entity = mw.wikibase.getEntityObject(propertyID) local claims if entity and entity.claims then claims = entity.claims['P2237'] end local out = {} local highestrank = nil if claims then if (claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == "wikibase-entityid") then -- if wiki-linked value output as link if possible for k, v in pairs(claims) do if v.rank ~= mw.wikibase.entity.claimRanks.RANK_DEPRECATED then local sitelink = mw.wikibase.sitelink("Q" .. v.mainsnak.datavalue.value["numeric-id"]) local label = mw.wikibase.label("Q" .. v.mainsnak.datavalue.value["numeric-id"]) if label == nil then -- let's try the fallback-languages local checkQ = mw.wikibase.getEntityObject("Q" .. v.mainsnak.datavalue.value["numeric-id"]) if checkQ then local i = 0 while i < #fallbacklang do i = i + 1 label = checkQ:getLabel( fallbacklang[i] ) if label ~= nil then break end end end if label == nil then -- no such luck, fall back to Q-values label = "Q" .. v.mainsnak.datavalue.value["numeric-id"] end end if sitelink and sitelink ~= label then out[#out + 1] = { output = "[[" .. sitelink .. "|" .. label .. "]]" } elseif sitelink then out[#out + 1] = { output = "[[" .. sitelink .. "]]" } else if fallback then out[#out + 1] = { output = "[[:d:Q" .. v.mainsnak.datavalue.value["numeric-id"] .. "|" .. label .. "]]<abbr title='" .. i18n['wiki-article-not-available'] .. "'>[*]</abbr>" } else out[#out + 1] = { output = label } end end out[#out].rank = v.rank out[#out].order = getOrder(v.qualifiers) highestrank = compareRank(highestrank, v.rank) end end end end -- Now we'll have to sort the table according to rank and order sortTableRankAndOrder(out) -- Now we'll make the output local i = 0 local ret = {} local list = 0 while i < #out do i = i + 1 -- check if the rank is within the highestrank if out[i].rank == highestrank then if list then list = list - 1 end ret[#ret + 1] = out[i].output if not list or list < 0 then if i < #out then break end end end end local ent = mw.wikibase.getEntityObject() ret[#ret + 1] = dump(ent.claims) return table.concat(ret, ", ") end end function p.getPropertyUnit(frame) getArguments(frame) return getUnitType(arguments.property, arguments.wiki_value) end local function addLinkback(str, property) local id = mw.wikibase.getEntityObject() if not id then return str end if type(id) == 'table' then id = id.id end local class = '' if property then class = 'wd_' .. string.lower(property) end local title = i18n['wikidata-linkback-edit'] local icon = '[%s [[File:Blue pencil.svg|%s|10px|baseline|link=]] ]' local url = mw.uri.fullUrl('d:' .. id .. '#' .. property, 'uselang=nb') url.fragment = property url = tostring(url) local v = mw.html.create('span') :addClass(class) :wikitext(str) :tag('span') :addClass('noprint plainlinks wikidata-linkback') :css('padding-left', '.5em') :wikitext(icon:format(url, title)) :allDone() return tostring(v) end -- -- Denne funksjonen kalles opp slik: {{#invoke:WikidataIB|rowProperty|P26}} -- den vil da returnere en tekst-streng som er en rad i en infoboks slik: <tr class="rad" valign="top"><th colspan="2">[Property-navn]</th><td colspan="2">[claim]</td></tr> -- property-navn og claim hentes fra wikidata -- andre argumenter som kan benyttes: -- property - angir hvilken property som skal benyttes, alternativ måte å spesifisere på: {{#invoke:WikidataIB|rowProperty|property=P26}} -- liste - angir at hvis det er flere verdier under en property skal de listes ut slik: <tr class="rad" valign="top"><th colspan="2">[Property-navn]</th><td colspan="2">[claim1], [claim2], ...</td></tr> -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|liste=1}} -- dato - angir om verdiene skal legges inn med dato i parantes i etterkant slik: <tr class="rad" valign="top"><th colspan="2">[Property-navn]</th><td colspan="2">[claim] (dato)</td></tr> -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|dato=<datoformat>}}, f.eks. {{#invoke:WikidataIB|rowProperty|P26|dato=j. F Y}} vil gi (31. desember 2015) -- denne kan også kombineres med "liste" -- verdi - standardverdi som benyttes dersom wikidata ikke har noen claims/verdier for den angitte egenskapen (property). Må da også spesifiseres sammen med "propertynavn". -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|verdi=Ola Normann}} -- pnavn - egenskapsnavn som benyttes dersom wikidata ikke har den angitte egenskapen (property). -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|pnavn=Ektefelle}} -- noedit - angir om en "editeringslink" som peker mot Wikidata IKKE skal legges på raden. Kun tilgjengelig hvis alle data hentes fra Wikidata. -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|noedit=1}} -- fallback - angir om lenker skal opprettes mot wikidata hvis lokal artikkel ikke finnes -- angis slik: {{#invoke:WikidataIB|rowProperty|P26|fallback=1}} -- function p.rowProperty(frame) getArguments(frame) local value = getValue(arguments.property, arguments.list, arguments.date, arguments.edit, arguments.fallback, arguments.usesuffix, arguments.suffix_from_wiki, arguments.usebounds, arguments.wiki_value) local retval = "" if value and value ~= "" then retval = retval .. '<tr class="rad" valign="top"><th colspan="2">' .. getProperty(arguments.property, arguments.label) .. '</th><td colspan="2"' if arguments.list then retval = retval .. ' class="reducible"' end retval = retval .. '>' if arguments.edit and (not arguments.wiki_value or arguments.wiki_value == "") then retval = retval .. addLinkback(value, arguments.property) else retval = retval .. value end retval = retval .. '</td></tr>' end return retval end function p.getPropertyValue(frame) -- Get argument "property" getArguments(frame) local value = getValue(arguments.property, arguments.list, arguments.date, arguments.edit, arguments.fallback, arguments.usesuffix, arguments.suffix_from_wiki, arguments.usebounds, arguments.wiki_value) local retval = "" if value and value ~= "" then if arguments.edit and (not arguments.wiki_value or arguments.wiki_value == "") then retval = addLinkback(value, arguments.property) else retval = value end end return retval end function p.getPropertyLabel(frame) getArguments(frame) return getProperty(arguments.property, arguments.label) end function p.dumpProperty(frame) getArguments(frame) local entity = mw.wikibase.getEntityObject(arguments.property) return dump(entity) end function p.dumpClaims(frame) getArguments(frame) local entity = mw.wikibase.getEntityObject() local claims = nil local retval = "" if entity and entity.claims and arguments.property then claims = entity.claims[arguments.property] elseif entity and entity.claims then claims = entity.claims end if claims then retval = dump(claims) end return retval end return p