Difference between revisions of "Module:Sandbox/Was a bee/Dump"

From blackwiki
Jump to navigation Jump to search
blackwiki>Was a bee
m
blackwiki>Was a bee
(←Replaced content with '-- Copied from Module:Wikidata. Main developer is User:RexxS. local p = {} -- internationalisation local i18n = { ["warnDump"] = "[[Category:Calle...')
Line 1: Line 1:
−
-- Copied from [[Module:Wikidata]]
+
-- Copied from [[Module:Wikidata]]. Main developer is [[User:RexxS]].
−
-- vim: set noexpandtab ft=lua ts=4 sw=4:
 
−
require('Module:No globals')
 
  
 
local p = {}
 
local p = {}
−
local debug = false
 
−
 
−
 
−
------------------------------------------------------------------------------
 
−
-- module local variables and functions
 
−
 
−
local wiki =
 
−
{
 
−
langcode = mw.language.getContentLanguage().code
 
−
}
 
  
 
-- internationalisation
 
-- internationalisation
 
local i18n =
 
local i18n =
 
{
 
{
−
["errors"] =
 
−
{
 
−
["property-not-found"] = "Property not found.",
 
−
["entity-not-found"] = "Wikidata entity not found.",
 
−
["unknown-claim-type"] = "Unknown claim type.",
 
−
["unknown-entity-type"] = "Unknown entity type.",
 
−
["qualifier-not-found"] = "Qualifier not found.",
 
−
["site-not-found"] = "Wikimedia project not found.",
 
−
["unknown-datetime-format"] = "Unknown datetime format.",
 
−
["local-article-not-found"] = "Article is not yet available in this wiki."
 
−
},
 
−
["datetime"] =
 
−
{
 
−
-- $1 is a placeholder for the actual number
 
−
[0] = "$1 billion years", -- precision: billion years
 
−
[1] = "$100 million years", -- precision: hundred million years
 
−
[2] = "$10 million years", -- precision: ten million years
 
−
[3] = "$1 million years", -- precision: million years
 
−
[4] = "$100,000 years", -- precision: hundred thousand years
 
−
[5] = "$10,000 years", -- precision: ten thousand years
 
−
[6] = "$1 millennium", -- precision: millennium
 
−
[7] = "$1 century", -- precision: century
 
−
[8] = "$1s", -- precision: decade
 
−
-- the following use the format of #time parser function
 
−
[9]  = "Y", -- precision: year,
 
−
[10] = "F Y", -- precision: month
 
−
[11] = "F j, Y", -- precision: day
 
−
[12] = "F j, Y ga", -- precision: hour
 
−
[13] = "F j, Y g:ia", -- precision: minute
 
−
[14] = "F j, Y g:i:sa", -- precision: second
 
−
["beforenow"] = "$1 BCE", -- how to format negative numbers for precisions 0 to 5
 
−
["afternow"] = "$1 CE", -- how to format positive numbers for precisions 0 to 5
 
−
["bc"] = '$1 "BCE"', -- how print negative years
 
−
["ad"] = "$1", -- how print positive years
 
−
-- the following are for function getDateValue() and getQualifierDateValue()
 
−
["default-format"] = "dmy", -- default value of the #3 (getDateValue) or
 
−
-- #4 (getQualifierDateValue) argument
 
−
["default-addon"] = "BC", -- default value of the #4 (getDateValue) or
 
−
-- #5 (getQualifierDateValue) argument
 
−
["prefix-addon"] = false, -- set to true for languages put "BC" in front of the
 
−
-- datetime string; or the addon will be suffixed
 
−
["addon-sep"] = " ", -- separator between datetime string and addon (or inverse)
 
−
["format"] = -- options of the 3rd argument
 
−
{
 
−
["mdy"] = "F j, Y",
 
−
["my"] = "F Y",
 
−
["y"] = "Y",
 
−
["dmy"] = "j F Y",
 
−
["ymd"] = "Y-m-d",
 
−
["ym"] = "Y-m"
 
−
}
 
−
},
 
−
["monolingualtext"] = '<span lang="%language">%text</span>',
 
 
["warnDump"] = "[[Category:Called function 'Dump' from module Wikidata]]",
 
["warnDump"] = "[[Category:Called function 'Dump' from module Wikidata]]",
−
["ordinal"] =
 
−
{
 
−
[1] = "st",
 
−
[2] = "nd",
 
−
[3] = "rd",
 
−
["default"] = "th"
 
−
}
 
 
}
 
}
−
 
−
--require("Module:i18n").loadI18n("Module:Wikidata/i18n", i18n)
 
−
-- got idea from [[:w:Module:Wd]]
 
−
local module_title; if ... == nil then
 
−
module_title = mw.getCurrentFrame():getTitle()
 
−
else
 
−
module_title = ...
 
−
end
 
−
require('Module:i18n').loadI18n(module_title..'/i18n', i18n)
 
−
 
−
-- this function needs to be internationalised along with the above:
 
−
-- takes cardinal numer as a numeric and returns the ordinal as a string
 
−
-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.
 
−
local function makeOrdinal (cardinal)
 
−
local ordsuffix = i18n.ordinal.default
 
−
if cardinal % 10 == 1 then
 
−
ordsuffix = i18n.ordinal[1]
 
−
elseif cardinal % 10 == 2 then
 
−
ordsuffix = i18n.ordinal[2]
 
−
elseif cardinal % 10 == 3 then
 
−
ordsuffix = i18n.ordinal[3]
 
−
end
 
−
-- In English, 1, 21, 31, etc. use 'st', but 11, 111, etc. use 'th'
 
−
-- similarly for 12 and 13, etc.
 
−
if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then
 
−
ordsuffix = i18n.ordinal.default
 
−
end
 
−
return tostring(cardinal) .. ordsuffix
 
−
end
 
−
 
−
local function printError(code)
 
−
return '<span class="error">' .. (i18n.errors[code] or code) .. '</span>'
 
−
end
 
−
local function parseDateFormat(f, timestamp, addon, prefix_addon, addon_sep)
 
−
local year_suffix
 
−
local tstr = ""
 
−
local lang_obj = mw.language.new(wiki.langcode)
 
−
local f_parts = mw.text.split(f, 'Y', true)
 
−
for idx, f_part in pairs(f_parts) do
 
−
year_suffix = ''
 
−
if string.match(f_part, "x[mijkot]$") then
 
−
-- for non-Gregorian year
 
−
f_part = f_part .. 'Y'
 
−
elseif idx < #f_parts then
 
−
-- supress leading zeros in year
 
−
year_suffix = lang_obj:formatDate('Y', timestamp)
 
−
year_suffix = string.gsub(year_suffix, '^0+', '', 1)
 
−
end
 
−
tstr = tstr .. lang_obj:formatDate(f_part, timestamp) .. year_suffix
 
−
end
 
−
if addon ~= "" and prefix_addon then
 
−
return addon .. addon_sep .. tstr
 
−
elseif addon ~= "" then
 
−
return tstr .. addon_sep .. addon
 
−
else
 
−
return tstr
 
−
end
 
−
end
 
−
local function parseDateValue(timestamp, date_format, date_addon)
 
−
local prefix_addon = i18n["datetime"]["prefix-addon"]
 
−
local addon_sep = i18n["datetime"]["addon-sep"]
 
−
local addon = ""
 
−
 
−
-- check for negative date
 
−
if string.sub(timestamp, 1, 1) == '-' then
 
−
timestamp = '+' .. string.sub(timestamp, 2)
 
−
addon = date_addon
 
−
end
 
−
local _date_format = i18n["datetime"]["format"][date_format]
 
−
if _date_format ~= nil then
 
−
return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)
 
−
else
 
−
return printError("unknown-datetime-format")
 
−
end
 
−
end
 
−
 
−
-- This local function combines the year/month/day/BC/BCE handling of parseDateValue{}
 
−
-- with the millennium/century/decade handling of formatDate()
 
−
local function parseDateFull(timestamp, precision, date_format, date_addon)
 
−
local prefix_addon = i18n["datetime"]["prefix-addon"]
 
−
local addon_sep = i18n["datetime"]["addon-sep"]
 
−
local addon = ""
 
−
 
−
-- check for negative date
 
−
if string.sub(timestamp, 1, 1) == '-' then
 
−
timestamp = '+' .. string.sub(timestamp, 2)
 
−
addon = date_addon
 
−
end
 
−
 
−
-- get the next four characters after the + (should be the year now in all cases)
 
−
-- ok, so this is dirty, but let's get it working first
 
−
local intyear = tonumber(string.sub(timestamp, 2, 5))
 
−
if intyear == 0 and precision <= 9 then
 
−
return ""
 
−
end
 
−
 
−
-- precision is 10000 years or more
 
−
if precision <= 5 then
 
−
local factor = 10 ^ ((5 - precision) + 4)
 
−
local y2 = math.ceil(math.abs(intyear) / factor)
 
−
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
 
−
if addon ~= "" then
 
−
-- negative date
 
−
relative = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
 
−
else
 
−
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
 
−
end
 
−
return relative
 
−
end
 
−
 
−
-- precision is decades (8), centuries (7) and millennia (6)
 
−
local era, card
 
−
if precision == 6 then
 
−
card = math.floor((intyear - 1) / 1000) + 1
 
−
era = mw.ustring.gsub(i18n.datetime[6], "$1", makeOrdinal(card))
 
−
end
 
−
if precision == 7 then
 
−
card = math.floor((intyear - 1) / 100) + 1
 
−
era = mw.ustring.gsub(i18n.datetime[7], "$1", makeOrdinal(card))
 
−
end
 
−
if precision == 8 then
 
−
era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(intyear) / 10) * 10))
 
−
end
 
−
if era then
 
−
if addon ~= "" then
 
−
era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
 
−
else
 
−
era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era)
 
−
end
 
−
return era
 
−
end
 
−
 
−
local _date_format = i18n["datetime"]["format"][date_format]
 
−
if _date_format ~= nil then
 
−
-- check for precision is year and override supplied date_format
 
−
if precision == 9 then
 
−
_date_format = i18n["datetime"][9]
 
−
end
 
−
return parseDateFormat(_date_format, timestamp, addon, prefix_addon, addon_sep)
 
−
else
 
−
return printError("unknown-datetime-format")
 
−
end
 
−
end
 
−
 
−
-- the "qualifiers" and "snaks" field have a respective "qualifiers-order" and "snaks-order" field
 
−
-- use these as the second parameter and this function instead of the built-in "pairs" function
 
−
-- to iterate over all qualifiers and snaks in the intended order.
 
−
local function orderedpairs(array, order)
 
−
if not order then return pairs(array) end
 
−
 
−
-- return iterator function
 
−
local i = 0
 
−
return function()
 
−
i = i + 1
 
−
if order[i] then
 
−
return order[i], array[order[i]]
 
−
end
 
−
end
 
−
end
 
−
 
−
-- precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
 
−
local function normalizeDate(date)
 
−
date = mw.text.trim(date, "+")
 
−
-- extract year
 
−
local yearstr = mw.ustring.match(date, "^\-?%d+")
 
−
local year = tonumber(yearstr)
 
−
-- remove leading zeros of year
 
−
return year .. mw.ustring.sub(date, #yearstr + 1), year
 
−
end
 
−
 
−
local function formatDate(date, precision, timezone)
 
−
precision = precision or 11
 
−
local date, year = normalizeDate(date)
 
−
if year == 0 and precision <= 9 then return "" end
 
−
 
−
-- precision is 10000 years or more
 
−
if precision <= 5 then
 
−
local factor = 10 ^ ((5 - precision) + 4)
 
−
local y2 = math.ceil(math.abs(year) / factor)
 
−
local relative = mw.ustring.gsub(i18n.datetime[precision], "$1", tostring(y2))
 
−
if year < 0 then
 
−
relative = mw.ustring.gsub(i18n.datetime.beforenow, "$1", relative)
 
−
else
 
−
relative = mw.ustring.gsub(i18n.datetime.afternow, "$1", relative)
 
−
end
 
−
return relative
 
−
end
 
−
 
−
-- precision is decades, centuries and millennia
 
−
local era
 
−
if precision == 6 then era = mw.ustring.gsub(i18n.datetime[6], "$1", tostring(math.floor((math.abs(year) - 1) / 1000) + 1)) end
 
−
if precision == 7 then era = mw.ustring.gsub(i18n.datetime[7], "$1", tostring(math.floor((math.abs(year) - 1) / 100) + 1)) end
 
−
if precision == 8 then era = mw.ustring.gsub(i18n.datetime[8], "$1", tostring(math.floor(math.abs(year) / 10) * 10)) end
 
−
if era then
 
−
if year < 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.bc, '"', ""), "$1", era)
 
−
elseif year > 0 then era = mw.ustring.gsub(mw.ustring.gsub(i18n.datetime.ad, '"', ""), "$1", era) end
 
−
return era
 
−
end
 
−
 
−
-- precision is year
 
−
if precision == 9 then
 
−
return year
 
−
end
 
−
 
−
-- precision is less than years
 
−
if precision > 9 then
 
−
--[[ the following code replaces the UTC suffix with the given negated timezone to convert the global time to the given local time
 
−
timezone = tonumber(timezone)
 
−
if timezone and timezone ~= 0 then
 
−
timezone = -timezone
 
−
timezone = string.format("%.2d%.2d", timezone / 60, timezone % 60)
 
−
if timezone[1] ~= '-' then timezone = "+" .. timezone end
 
−
date = mw.text.trim(date, "Z") .. " " .. timezone
 
−
end
 
−
]]--
 
−
 
−
local formatstr = i18n.datetime[precision]
 
−
if year == 0 then formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], "")
 
−
elseif year < 0 then
 
−
-- Mediawiki formatDate doesn't support negative years
 
−
date = mw.ustring.sub(date, 2)
 
−
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.bc, "$1", i18n.datetime[9]))
 
−
elseif year > 0 and i18n.datetime.ad ~= "$1" then
 
−
formatstr = mw.ustring.gsub(formatstr, i18n.datetime[9], mw.ustring.gsub(i18n.datetime.ad, "$1", i18n.datetime[9]))
 
−
end
 
−
return mw.language.new(wiki.langcode):formatDate(formatstr, date)
 
−
end
 
−
end
 
−
 
−
local function printDatavalueEntity(data, parameter)
 
−
-- data fields: entity-type [string], numeric-id [int, Wikidata id]
 
−
local id
 
−
 
−
if data["entity-type"] == "item" then id = "Q" .. data["numeric-id"]
 
−
elseif data["entity-type"] == "property" then id = "P" .. data["numeric-id"]
 
−
else return printError("unknown-entity-type")
 
−
end
 
−
 
−
if parameter then
 
−
if parameter == "link" then
 
−
local linkTarget = mw.wikibase.sitelink(id)
 
−
local linkName = mw.wikibase.label(id)
 
−
if linkTarget then
 
−
-- if there is a local Wikipedia article link to it using the label or the article title
 
−
return "[[" .. linkTarget .. "|" .. (linkName or linkTarget) .. "]]"
 
−
else
 
−
-- if there is no local Wikipedia article output the label or link to the Wikidata object to let the user input a proper label
 
−
if linkName then return linkName else return "[[:d:" .. id .. "|" .. id .. "]]" end
 
−
end
 
−
else
 
−
return data[parameter]
 
−
end
 
−
else
 
−
return mw.wikibase.label(id) or id
 
−
end
 
−
end
 
−
 
−
local function printDatavalueTime(data, parameter)
 
−
-- data fields: time [ISO 8601 time], timezone [int in minutes], before [int], after [int], precision [int], calendarmodel [wikidata URI]
 
−
--  precision: 0 - billion years, 1 - hundred million years, ..., 6 - millennia, 7 - century, 8 - decade, 9 - year, 10 - month, 11 - day, 12 - hour, 13 - minute, 14 - second
 
−
--  calendarmodel: e.g. http://www.wikidata.org/entity/Q1985727 for the proleptic Gregorian calendar or http://www.wikidata.org/wiki/Q11184 for the Julian calendar]
 
−
if parameter then
 
−
if parameter == "calendarmodel" then data.calendarmodel = mw.ustring.match(data.calendarmodel, "Q%d+") -- extract entity id from the calendar model URI
 
−
elseif parameter == "time" then data.time = normalizeDate(data.time) end
 
−
return data[parameter]
 
−
else
 
−
return formatDate(data.time, data.precision, data.timezone)
 
−
end
 
−
end
 
−
 
−
local function printDatavalueMonolingualText(data, parameter)
 
−
-- data fields: language [string], text [string]
 
−
if parameter then
 
−
return data[parameter]
 
−
else
 
−
local result = mw.ustring.gsub(mw.ustring.gsub(i18n.monolingualtext, "%%language", data["language"]), "%%text", data["text"])
 
−
return result
 
−
end
 
−
end
 
−
 
−
local function findClaims(entity, property)
 
−
if not property or not entity or not entity.claims then return end
 
−
 
−
if mw.ustring.match(property, "^P%d+$") then
 
−
-- if the property is given by an id (P..) access the claim list by this id
 
−
return entity.claims[property]
 
−
else
 
−
property = mw.wikibase.resolvePropertyId(property)
 
−
if not property then return end
 
−
 
−
return entity.claims[property]
 
−
end
 
−
end
 
−
 
−
local function getSnakValue(snak, parameter)
 
−
if snak.snaktype == "value" then
 
−
-- call the respective snak parser
 
−
if snak.datavalue.type == "string" then return snak.datavalue.value
 
−
elseif snak.datavalue.type == "globecoordinate" then return printDatavalueCoordinate(snak.datavalue.value, parameter)
 
−
elseif snak.datavalue.type == "quantity" then return printDatavalueQuantity(snak.datavalue.value, parameter)
 
−
elseif snak.datavalue.type == "time" then return printDatavalueTime(snak.datavalue.value, parameter)
 
−
elseif snak.datavalue.type == "wikibase-entityid" then return printDatavalueEntity(snak.datavalue.value, parameter)
 
−
elseif snak.datavalue.type == "monolingualtext" then return printDatavalueMonolingualText(snak.datavalue.value, parameter)
 
−
end
 
−
end
 
−
return mw.wikibase.renderSnak(snak)
 
−
end
 
−
 
−
local function getQualifierSnak(claim, qualifierId)
 
−
-- a "snak" is Wikidata terminology for a typed key/value pair
 
−
-- a claim consists of a main snak holding the main information of this claim,
 
−
-- as well as a list of attribute snaks and a list of references snaks
 
−
if qualifierId then
 
−
-- search the attribute snak with the given qualifier as key
 
−
if claim.qualifiers then
 
−
local qualifier = claim.qualifiers[qualifierId]
 
−
if qualifier then return qualifier[1] end
 
−
end
 
−
return nil, printError("qualifier-not-found")
 
−
else
 
−
-- otherwise return the main snak
 
−
return claim.mainsnak
 
−
end
 
−
end
 
−
 
−
local function getValueOfClaim(claim, qualifierId, parameter)
 
−
local error
 
−
local snak
 
−
snak, error = getQualifierSnak(claim, qualifierId)
 
−
if snak then
 
−
return getSnakValue(snak, parameter)
 
−
else
 
−
return nil, error
 
−
end
 
−
end
 
−
 
−
local function getReferences(frame, claim)
 
−
local result = ""
 
−
-- traverse through all references
 
−
for ref in pairs(claim.references or {}) do
 
−
local refparts
 
−
-- traverse through all parts of the current reference
 
−
for snakkey, snakval in orderedpairs(claim.references[ref].snaks or {}, claim.references[ref]["snaks-order"]) do
 
−
if refparts then refparts = refparts .. ", " else refparts = "" end
 
−
-- output the label of the property of the reference part, e.g. "imported from" for P143
 
−
refparts = refparts .. tostring(mw.wikibase.label(snakkey)) .. ": "
 
−
-- output all values of this reference part, e.g. "German Wikipedia" and "English Wikipedia" if the referenced claim was imported from both sites
 
−
for snakidx = 1, #snakval do
 
−
if snakidx > 1 then refparts = refparts .. ", " end
 
−
refparts = refparts .. getSnakValue(snakval[snakidx])
 
−
end
 
−
end
 
−
if refparts then result = result .. frame:extensionTag("ref", refparts) end
 
−
end
 
−
return result
 
−
end
 
−
 
−
local function parseInput(frame)
 
−
local qid = frame.args.qid
 
−
if qid and (#qid == 0) then qid = nil end
 
−
local propertyID = mw.text.trim(frame.args[1] or "")
 
−
local input_parm = mw.text.trim(frame.args[2] or "")
 
−
if input_parm ~= "FETCH_WIKIDATA" then
 
−
return false, input_parm, nil, nil
 
−
end
 
−
local entity = mw.wikibase.getEntityObject(qid)
 
−
local claims
 
−
if entity and entity.claims then
 
−
claims = entity.claims[propertyID]
 
−
if not claims then
 
−
return false, "", nil, nil
 
−
end
 
−
else
 
−
return false, "", nil, nil
 
−
end
 
−
return true, entity, claims, propertyID
 
−
end
 
−
local function isType(claims, type)
 
−
return claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == type
 
−
end
 
−
local function getValue(entity, claims, propertyID, delim, labelHook)
 
−
if labelHook == nil then
 
−
labelHook = function (qnumber)
 
−
return nil;
 
−
end
 
−
end
 
−
if isType(claims, "wikibase-entityid") then
 
−
local out = {}
 
−
for k, v in pairs(claims) do
 
−
local qnumber = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
 
−
local sitelink = mw.wikibase.sitelink(qnumber)
 
−
local label = labelHook(qnumber) or mw.wikibase.label(qnumber) or qnumber
 
−
if sitelink then
 
−
out[#out + 1] = "[[" .. sitelink .. "|" .. label .. "]]"
 
−
else
 
−
out[#out + 1] = "[[:d:" .. qnumber .. "|" .. label .. "]]<abbr title='" .. i18n["errors"]["local-article-not-found"] .. "'>[*]</abbr>"
 
−
end
 
−
end
 
−
return table.concat(out, delim)
 
−
else
 
−
-- just return best values
 
−
return entity:formatPropertyValues(propertyID).value
 
−
end
 
−
end
 
−
 
−
------------------------------------------------------------------------------
 
−
-- module global functions
 
−
 
−
if debug then
 
−
function p.inspectI18n(frame)
 
−
local val = i18n
 
−
for _, key in pairs(frame.args) do
 
−
key = mw.text.trim(key)
 
−
val = val[key]
 
−
end
 
−
return val
 
−
end
 
−
end
 
−
 
−
function p.descriptionIn(frame)
 
−
local langcode = frame.args[1]
 
−
local id = frame.args[2]
 
−
-- return description of a Wikidata entity in the given language or the default language of this Wikipedia site
 
−
return mw.wikibase.getEntityObject(id).descriptions[langcode or wiki.langcode].value
 
−
end
 
−
 
−
function p.labelIn(frame)
 
−
local langcode = frame.args[1]
 
−
local id = frame.args[2]
 
−
-- return label of a Wikidata entity in the given language or the default language of this Wikipedia site
 
−
return mw.wikibase.getEntityObject(id).labels[langcode or wiki.langcode].value
 
−
end
 
−
 
−
-- This is used to get a value, or a comma separated list of them if multiple values exist
 
−
p.getValue = function(frame)
 
−
local delimdefault = ", " -- **internationalise later**
 
−
local delim = frame.args.delimiter or ""
 
−
delim = string.gsub(delim, '"', '')
 
−
if #delim == 0 then
 
−
delim = delimdefault
 
−
end
 
−
local go, errorOrentity, claims, propertyID = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
return getValue(errorOrentity, claims, propertyID, delim)
 
−
end
 
−
 
−
-- Same as above, but uses the short name property for label if available.
 
−
p.getValueShortName = function(frame)
 
−
local go, errorOrentity, claims, propertyID = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
-- if wiki-linked value output as link if possible
 
−
local function labelHook (qnumber)
 
−
local label
 
−
local claimEntity = mw.wikibase.getEntity(qnumber)
 
−
if claimEntity ~= nil then
 
−
if claimEntity.claims.P1813 then
 
−
for k2, v2 in pairs(claimEntity.claims.P1813) do
 
−
if v2.mainsnak.datavalue.value.language == "en" then
 
−
label = v2.mainsnak.datavalue.value.text
 
−
end
 
−
end
 
−
end
 
−
end
 
−
if label == nil or label == "" then return nil end
 
−
return label
 
−
end
 
−
return getValue(errorOrentity, claims, propertyID, ", ", labelHook);
 
−
end
 
−
 
−
-- This is used to get a value, or a comma separated list of them if multiple values exist
 
−
-- from an arbitrary entry by using its QID.
 
−
-- Use : {{#invoke:Wikidata|getValueFromID|<ID>|<Property>|FETCH_WIKIDATA}}
 
−
-- E.g.: {{#invoke:Wikidata|getValueFromID|Q151973|P26|FETCH_WIKIDATA}} - to fetch value of 'spouse' (P26) from 'Richard Burton' (Q151973)
 
−
-- Please use sparingly - this is an *expensive call*.
 
−
p.getValueFromID = function(frame)
 
−
local itemID = mw.text.trim(frame.args[1] or "")
 
−
local propertyID = mw.text.trim(frame.args[2] or "")
 
−
local input_parm = mw.text.trim(frame.args[3] or "")
 
−
if input_parm == "FETCH_WIKIDATA" then
 
−
local entity = mw.wikibase.getEntity(itemID)
 
−
local claims
 
−
if entity and entity.claims then
 
−
claims = entity.claims[propertyID]
 
−
end
 
−
if claims then
 
−
return getValue(entity, claims, propertyID, ", ")
 
−
else
 
−
return ""
 
−
end
 
−
else
 
−
return input_parm
 
−
end
 
−
end
 
−
local function getQualifier(frame, outputHook)
 
−
local propertyID = mw.text.trim(frame.args[1] or "")
 
−
local qualifierID = mw.text.trim(frame.args[2] or "")
 
−
local input_parm = mw.text.trim(frame.args[3] or "")
 
−
if input_parm == "FETCH_WIKIDATA" then
 
−
local entity = mw.wikibase.getEntityObject()
 
−
if entity.claims[propertyID] ~= nil then
 
−
local out = {}
 
−
for k, v in pairs(entity.claims[propertyID]) do
 
−
for k2, v2 in pairs(v.qualifiers[qualifierID]) do
 
−
if v2.snaktype == 'value' then
 
−
out[#out + 1] = outputHook(v2);
 
−
end
 
−
end
 
−
end
 
−
return table.concat(out, ", "), true
 
−
else
 
−
return "", false
 
−
end
 
−
else
 
−
return input_parm, false
 
−
end
 
−
end
 
−
p.getQualifierValue = function(frame)
 
−
local function outputValue(value)
 
−
local qnumber = "Q" .. value.datavalue.value["numeric-id"]
 
−
if (mw.wikibase.sitelink(qnumber)) then
 
−
return "[[" .. mw.wikibase.sitelink(qnumber) .. "]]"
 
−
else
 
−
return "[[:d:" .. qnumber .. "|" ..qnumber .. "]]<abbr title='" .. i18n["errors"]["local-article-not-found"] .. "'>[*]</abbr>"
 
−
end
 
−
end
 
−
return (getQualifier(frame, outputValue))
 
−
end
 
−
 
−
-- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators
 
−
p.getRawValue = function(frame)
 
−
local go, errorOrentity, claims, propertyID = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
 
−
-- if number type: remove thousand separators, bounds and units
 
−
if isType(claims, "quantity") then
 
−
result = mw.ustring.gsub(result, "(%d),(%d)", "%1%2")
 
−
result = mw.ustring.gsub(result, "(%d)±.*", "%1")
 
−
end
 
−
return result
 
−
end
 
−
 
−
-- This is used to get the unit name for the numeric value returned by getRawValue
 
−
p.getUnits = function(frame)
 
−
local go, errorOrentity, claims, propertyID = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
local result = entity:formatPropertyValues(propertyID, mw.wikibase.entity.claimRanks).value
 
−
if isType(claims, "quantity") then
 
−
result = mw.ustring.sub(result, mw.ustring.find(result, " ")+1, -1)
 
−
end
 
−
return result
 
−
end
 
−
 
−
-- This is used to get the unit's QID to use with the numeric value returned by getRawValue
 
−
p.getUnitID = function(frame)
 
−
local go, errorOrentity, claims = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
local result
 
−
if isType(claims, "quantity") then
 
−
-- get the url for the unit entry on Wikidata:
 
−
result = claims[1].mainsnak.datavalue.value.unit
 
−
-- and just reurn the last bit from "Q" to the end (which is the QID):
 
−
result = mw.ustring.sub(result, mw.ustring.find(result, "Q"), -1)
 
−
end
 
−
return result
 
−
end
 
−
 
−
p.getRawQualifierValue = function(frame)
 
−
local function outputHook(value)
 
−
if value.datavalue.value["numeric-id"] then
 
−
return mw.wikibase.label("Q" .. value.datavalue.value["numeric-id"])
 
−
else
 
−
return value.datavalue.value
 
−
end
 
−
end
 
−
local ret, gotData = getQualifier(frame, outputHook)
 
−
if gotData then
 
−
ret = string.upper(string.sub(ret, 1, 1)) .. string.sub(ret, 2)
 
−
end
 
−
return ret
 
−
end
 
−
 
−
-- This is used to get a date value for date_of_birth (P569), etc. which won't be linked
 
−
-- Dates and times are stored in ISO 8601 format (sort of).
 
−
-- At present the local formatDate(date, precision, timezone) function doesn't handle timezone
 
−
-- So I'll just supply "Z" in the call to formatDate below:
 
−
p.getDateValue = function(frame)
 
−
local date_format = mw.text.trim(frame.args[3] or i18n["datetime"]["default-format"])
 
−
local date_addon = mw.text.trim(frame.args[4] or i18n["datetime"]["default-addon"])
 
−
local go, errorOrentity, claims = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
local out = {}
 
−
for k, v in pairs(claims) do
 
−
if v.mainsnak.datavalue.type == 'time' then
 
−
local timestamp = v.mainsnak.datavalue.value.time
 
−
local dateprecision = v.mainsnak.datavalue.value.precision
 
−
-- A year can be stored like this: "+1872-00-00T00:00:00Z",
 
−
-- which is processed here as if it were the day before "+1872-01-01T00:00:00Z",
 
−
-- and that's the last day of 1871, so the year is wrong.
 
−
-- So fix the month 0, day 0 timestamp to become 1 January instead:
 
−
timestamp = timestamp:gsub("%-00%-00T", "-01-01T")
 
−
out[#out + 1] = parseDateFull(timestamp, dateprecision, date_format, date_addon)
 
−
end
 
−
end
 
−
return table.concat(out, ", ")
 
−
end
 
−
p.getQualifierDateValue = function(frame)
 
−
local date_format = mw.text.trim(frame.args[4] or i18n["datetime"]["default-format"])
 
−
local date_addon = mw.text.trim(frame.args[5] or i18n["datetime"]["default-addon"])
 
−
local function outputHook(value)
 
−
local timestamp = value.datavalue.value.time
 
−
return parseDateValue(timestamp, date_format, date_addon)
 
−
end
 
−
return (getQualifier(frame, outputHook))
 
−
end
 
−
 
−
-- This is used to fetch all of the images with a particular property, e.g. image (P18), Gene Atlas Image (P692), etc.
 
−
-- Parameters are | propertyID | value / FETCH_WIKIDATA / nil | separator (default=space) | size (default=frameless)
 
−
-- It will return a standard wiki-markup [[File:Filename | size]] for each image with a selectable size and separator (which may be html)
 
−
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA}}
 
−
-- e.g. {{#invoke:Wikidata|getImages|P18|FETCH_WIKIDATA|<br>|250px}}
 
−
-- If a property is chosen that is not of type "commonsMedia", it will return empty text.
 
−
p.getImages = function(frame)
 
−
local sep = mw.text.trim(frame.args[3] or " ")
 
−
local imgsize = mw.text.trim(frame.args[4] or "frameless")
 
−
local go, errorOrentity, claims = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then
 
−
local out = {}
 
−
for k, v in pairs(claims) do
 
−
local filename = v.mainsnak.datavalue.value
 
−
out[#out + 1] = "[[File:" .. filename .. "|" .. imgsize .. "]]"
 
−
end
 
−
return table.concat(out, sep)
 
−
else
 
−
return ""
 
−
end
 
−
end
 
−
 
−
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323)
 
−
-- which are then linked to http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/01.1.00.005%20Entity%20TA98%20EN.htm
 
−
-- uses the newer mw.wikibase calls instead of directly using the snaks
 
−
-- formatPropertyValues returns a table with the P1323 values concatenated with ", " so we have to split them out into a table in order to construct the return string
 
−
p.getTAValue = function(frame)
 
−
local ent = mw.wikibase.getEntityObject()
 
−
local props = ent:formatPropertyValues('P1323')
 
−
local out = {}
 
−
local t = {}
 
−
for k, v in pairs(props) do
 
−
if k == 'value' then
 
−
t = mw.text.split( v, ", ")
 
−
for k2, v2 in pairs(t) do
 
−
out[#out + 1] = "[http://www.unifr.ch/ifaa/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]"
 
−
end
 
−
end
 
−
end
 
−
local ret = table.concat(out, "<br> ")
 
−
if #ret == 0 then
 
−
ret = "Invalid TA"
 
−
end
 
−
return ret
 
−
end
 
−
 
−
--[[
 
−
This is used to return an image legend from Wikidata
 
−
image is property P18
 
−
image legend is property P2096
 
−
 
−
Call as {{#invoke:Wikidata |getImageLegend | <PARAMETER> | lang=<ISO-639code> |id=<QID>}}
 
−
Returns PARAMETER, unless it is equal to "FETCH_WIKIDATA", from Item QID (expensive call)
 
−
If QID is omitted or blank, the current article is used (not an expensive call)
 
−
If lang is omitted, it uses the local wiki language, otherwise it uses the provided ISO-639 language code
 
−
ISO-639: https://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqisocodes.html#wp1252447
 
−
 
−
Ranks are: 'preferred' > 'normal'
 
−
This returns the label from the first image with 'preferred' rank
 
−
Or the label from the first image with 'normal' rank if preferred returns nothing
 
−
Ranks: https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua
 
−
]]
 
−
 
−
p.getImageLegend = function(frame)
 
−
-- look for named parameter id; if it's blank make it nil
 
−
local id = frame.args.id
 
−
if id and (#id == 0) then
 
−
id = nil
 
−
end
 
−
 
−
-- look for named parameter lang
 
−
-- it should contain a two-character ISO-639 language code
 
−
-- if it's blank fetch the language of the local wiki
 
−
local lang = frame.args.lang
 
−
if (not lang) or (#lang < 2) then
 
−
lang = mw.language.getContentLanguage().code
 
−
end
 
−
 
−
-- first unnamed parameter is the local parameter, if supplied
 
−
local input_parm = mw.text.trim(frame.args[1] or "")
 
−
if input_parm == "FETCH_WIKIDATA" then
 
−
local ent = mw.wikibase.getEntityObject(id)
 
−
local imgs
 
−
if ent and ent.claims then
 
−
imgs = ent.claims.P18
 
−
end
 
−
local imglbl
 
−
if imgs then
 
−
-- look for an image with 'preferred' rank
 
−
for k1, v1 in pairs(imgs) do
 
−
if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P2096 then
 
−
local imglbls = v1.qualifiers.P2096
 
−
for k2, v2 in pairs(imglbls) do
 
−
if v2.datavalue.value.language == lang then
 
−
imglbl = v2.datavalue.value.text
 
−
break
 
−
end
 
−
end
 
−
end
 
−
end
 
−
-- if we don't find one, look for an image with 'normal' rank
 
−
if (not imglbl) then
 
−
for k1, v1 in pairs(imgs) do
 
−
if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P2096 then
 
−
local imglbls = v1.qualifiers.P2096
 
−
for k2, v2 in pairs(imglbls) do
 
−
if v2.datavalue.value.language == lang then
 
−
imglbl = v2.datavalue.value.text
 
−
break
 
−
end
 
−
end
 
−
end
 
−
end
 
−
end
 
−
end
 
−
return imglbl
 
−
else
 
−
return input_parm
 
−
end
 
−
end
 
−
 
−
-- This is used to get the QIDs of all of the values of a property, as a comma separated list if multiple values exist
 
−
-- Usage: {{#invoke:Wikidata |getPropertyIDs |<PropertyID> |FETCH_WIKIDATA}}
 
−
-- Usage: {{#invoke:Wikidata |getPropertyIDs |<PropertyID> |<InputParameter> |qid=<QID>}}
 
−
 
−
p.getPropertyIDs = function(frame)
 
−
local go, errorOrentity, propclaims = parseInput(frame)
 
−
if not go then
 
−
return errorOrentity
 
−
end
 
−
local entity = errorOrentity
 
−
-- if wiki-linked value collect the QID in a table
 
−
if (propclaims[1] and propclaims[1].mainsnak.snaktype == "value" and propclaims[1].mainsnak.datavalue.type == "wikibase-entityid") then
 
−
local out = {}
 
−
for k, v in pairs(propclaims) do
 
−
out[#out + 1] = "Q" .. v.mainsnak.datavalue.value["numeric-id"]
 
−
end
 
−
return table.concat(out, ", ")
 
−
else
 
−
-- not a wikibase-entityid, so return empty
 
−
return ""
 
−
end
 
−
end
 
−
 
−
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
 
−
function p.pageId(frame)
 
−
local entity = mw.wikibase.getEntityObject()
 
−
if not entity then return nil else return entity.id end
 
−
end
 
−
 
−
function p.claim(frame)
 
−
local property = frame.args[1] or ""
 
−
local id = frame.args["id"]
 
−
local qualifierId = frame.args["qualifier"]
 
−
local parameter = frame.args["parameter"]
 
−
local list = frame.args["list"]
 
−
local references = frame.args["references"]
 
−
local showerrors = frame.args["showerrors"]
 
−
local default = frame.args["default"]
 
−
if default then showerrors = nil end
 
−
 
−
-- get wikidata entity
 
−
local entity = mw.wikibase.getEntityObject(id)
 
−
if not entity then
 
−
if showerrors then return printError("entity-not-found") else return default end
 
−
end
 
−
-- fetch the first claim of satisfying the given property
 
−
local claims = findClaims(entity, property)
 
−
if not claims or not claims[1] then
 
−
if showerrors then return printError("property-not-found") else return default end
 
−
end
 
−
 
−
-- get initial sort indices
 
−
local sortindices = {}
 
−
for idx in pairs(claims) do
 
−
sortindices[#sortindices + 1] = idx
 
−
end
 
−
-- sort by claim rank
 
−
local comparator = function(a, b)
 
−
local rankmap = { deprecated = 2, normal = 1, preferred = 0 }
 
−
local ranka = rankmap[claims[a].rank or "normal"] .. string.format("%08d", a)
 
−
local rankb = rankmap[claims[b].rank or "normal"] .. string.format("%08d", b)
 
−
return ranka < rankb
 
−
end
 
−
table.sort(sortindices, comparator)
 
−
 
−
local result
 
−
local error
 
−
if list then
 
−
local value
 
−
-- iterate over all elements and return their value (if existing)
 
−
result = {}
 
−
for idx in pairs(claims) do
 
−
local claim = claims[sortindices[idx]]
 
−
value, error = getValueOfClaim(claim, qualifierId, parameter)
 
−
if not value and showerrors then value = error end
 
−
if value and references then value = value .. getReferences(frame, claim) end
 
−
result[#result + 1] = value
 
−
end
 
−
result = table.concat(result, list)
 
−
else
 
−
-- return first element
 
−
local claim = claims[sortindices[1]]
 
−
result, error = getValueOfClaim(claim, qualifierId, parameter)
 
−
if result and references then result = result .. getReferences(frame, claim) end
 
−
end
 
−
 
−
if result then return result else
 
−
if showerrors then return error else return default end
 
−
end
 
−
end
 
−
 
−
-- look into entity object
 
−
function p.ViewSomething(frame)
 
−
local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
 
−
local id = f.args.id
 
−
if id and (#id == 0) then
 
−
id = nil
 
−
end
 
−
local data = mw.wikibase.getEntityObject(id)
 
−
if not data then
 
−
return nil
 
−
end
 
−
 
−
local i = 1
 
−
while true do
 
−
local index = f.args[i]
 
−
if not index then
 
−
if type(data) == "table" then
 
−
return mw.text.jsonEncode(data, mw.text.JSON_PRESERVE_KEYS + mw.text.JSON_PRETTY)
 
−
else
 
−
return tostring(data)
 
−
end
 
−
end
 
−
 
−
data = data[index] or data[tonumber(index)]
 
−
if not data then
 
−
return
 
−
end
 
−
 
−
i = i + 1
 
−
end
 
−
end
 
−
 
−
-- getting sitelink of a given wiki
 
−
-- get sitelink of current item if qid not supplied
 
−
function p.getSiteLink(frame)
 
−
local qid = frame.args.qid
 
−
if qid == "" then qid = nil end
 
−
local f = mw.text.trim( frame.args[1] or "")
 
−
local entity = mw.wikibase.getEntity(qid)
 
−
if not entity then
 
−
return
 
−
end
 
−
local link = entity:getSitelink( f )
 
−
if not link then
 
−
return
 
−
end
 
−
return link
 
−
end
 
  
 
function p.Dump(frame)
 
function p.Dump(frame)

Revision as of 04:37, 10 June 2018

→ See Template:Dump.



-- Copied from [[Module:Wikidata]]. Main developer is [[User:RexxS]].

local p = {}

-- internationalisation
local i18n =
{
	["warnDump"] = "[[Category:Called function 'Dump' from module Wikidata]]",
}

function p.Dump(frame)
	local f = (frame.args[1] or frame.args.id) and frame or frame:getParent()
	local data = mw.wikibase.getEntityObject(f.args.id)
	local width = f.args.width or "100%"
	local height = f.args.height or ""
	local overflowY
	if (height ~= nil) and (height ~= "") then
		overflowY = "scroll"
	else
		overflowY = ""
	end
	mw.logObject(height)
	mw.logObject(overflowY)
	if not data then
		return i18n.warnDump
	end

	local i = 1
	while true do
		local index = f.args[i]
		if (not index) or (index == "") then
			return f:extensionTag{ name = 'syntaxhighlight', content = mw.dumpObject(data), args = {lang = "javascript", style = "width: " .. width .. ";"  .. "height: " .. height .. ";" .. "overflow-y: " .. overflowY .. ";" .. "overflow-x: hidden;" } } .. i18n.warnDump
		end

		data = data[index] or data[tonumber(index)]
		if not data then
			return i18n.warnDump
		end

		i = i + 1
	end
end

return p