1,196
edits
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
-- vim: set noexpandtab ft=lua ts=4 sw=4: | -- vim: set noexpandtab ft=lua ts=4 sw=4: | ||
require(' | require('strict') | ||
local p = {} | local p = {} | ||
Line 362: | Line 362: | ||
local function findClaims(entity, property) | local function findClaims(entity, property) | ||
if not property or not entity or not | if not property or not entity or not entity.claims then return end | ||
if mw.ustring.match(property, "^P%d+$") then | if mw.ustring.match(property, "^P%d+$") then | ||
-- if the property is given by an id (P..) access the claim list by this id | -- if the property is given by an id (P..) access the claim list by this id | ||
return | return entity.claims[property] | ||
else | else | ||
property = mw.wikibase.resolvePropertyId(property) | property = mw.wikibase.resolvePropertyId(property) | ||
if not property then return end | if not property then return end | ||
return | return entity.claims[property] | ||
end | end | ||
end | end | ||
Line 402: | Line 402: | ||
else | else | ||
-- otherwise return the main snak | -- otherwise return the main snak | ||
return claim | return claim.mainsnak | ||
end | end | ||
end | end | ||
Line 439: | Line 439: | ||
local function parseInput(frame) | local function parseInput(frame) | ||
local qid = frame.args.qid | local qid = frame.args.qid | ||
if qid and (#qid == 0) then qid = nil end | if qid and (#qid == 0) then qid = nil end | ||
local propertyID = mw.text.trim(frame.args[1] or "") | local propertyID = mw.text.trim(frame.args[1] or "") | ||
Line 446: | Line 446: | ||
return false, input_parm, nil, nil | return false, input_parm, nil, nil | ||
end | end | ||
local entity = mw.wikibase.getEntity(qid) | |||
local claims | local claims | ||
if | if entity and entity.claims then | ||
claims = | claims = entity.claims[propertyID] | ||
if not claims then | if not claims then | ||
return false, "", nil, nil | return false, "", nil, nil | ||
Line 455: | Line 456: | ||
return false, "", nil, nil | return false, "", nil, nil | ||
end | end | ||
return true, claims | return true, entity, claims, propertyID | ||
end | end | ||
local function isType(claims, type) | local function isType(claims, type) | ||
return claims and claims.mainsnak.snaktype == "value" and claims.mainsnak.datavalue.type == type | return claims[1] and claims[1].mainsnak.snaktype == "value" and claims[1].mainsnak.datavalue.type == type | ||
end | end | ||
local function getValue(claims, delim, labelHook) | local function getValue(entity, claims, propertyID, delim, labelHook) | ||
if labelHook == nil then | if labelHook == nil then | ||
labelHook = function (qnumber) | labelHook = function (qnumber) | ||
Line 466: | Line 467: | ||
end | end | ||
end | end | ||
if isType(claims, "wikibase-entityid") then | |||
if claims | local out = {} | ||
local | for k, v in pairs(claims) do | ||
local qnumber = "Q" .. v.mainsnak.datavalue.value["numeric-id"] | |||
local sitelink = mw.wikibase.getSitelink(qnumber) | |||
local label = labelHook(qnumber) or mw.wikibase.getLabel(qnumber) or qnumber | |||
if sitelink then | |||
out[#out + 1] = "[[" .. sitelink .. "|" .. label .. "]]" | |||
else | else | ||
out[#out + 1] = | out[#out + 1] = "[[:d:" .. qnumber .. "|" .. label .. "]]<abbr title='" .. i18n["errors"]["local-article-not-found"] .. "'>[*]</abbr>" | ||
end | end | ||
end | end | ||
return table.concat(out, delim) | |||
else | |||
-- just return best values | |||
return entity:formatPropertyValues(propertyID).value | |||
end | end | ||
end | end | ||
Line 524: | Line 522: | ||
delim = delimdefault | delim = delimdefault | ||
end | end | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims, propertyID = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
return getValue(claims, delim) | return getValue(errorOrentity, claims, propertyID, delim) | ||
end | end | ||
-- Same as above, but uses the short name property for label if available. | -- Same as above, but uses the short name property for label if available. | ||
p.getValueShortName = function(frame) | p.getValueShortName = function(frame) | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims, propertyID = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local entity = errorOrentity | |||
-- if wiki-linked value output as link if possible | -- if wiki-linked value output as link if possible | ||
local function labelHook (qnumber) | local function labelHook (qnumber) | ||
local label | local label | ||
local | local claimEntity = mw.wikibase.getEntity(qnumber) | ||
if claimEntity ~= nil then | |||
if | if claimEntity.claims.P1813 then | ||
for k2, v2 in pairs(claimEntity.claims.P1813) do | |||
if | if v2.mainsnak.datavalue.value.language == "en" then | ||
label = | label = v2.mainsnak.datavalue.value.text | ||
end | end | ||
end | end | ||
end | end | ||
Line 554: | Line 552: | ||
return label | return label | ||
end | end | ||
return getValue(claims, ", ", labelHook); | return getValue(errorOrentity, claims, propertyID, ", ", labelHook); | ||
end | end | ||
Line 567: | Line 565: | ||
local input_parm = mw.text.trim(frame.args[3] or "") | local input_parm = mw.text.trim(frame.args[3] or "") | ||
if input_parm == "FETCH_WIKIDATA" then | if input_parm == "FETCH_WIKIDATA" then | ||
local entity = mw.wikibase.getEntity(itemID) | |||
local claims | local claims | ||
if | if entity and entity.claims then | ||
claims = | claims = entity.claims[propertyID] | ||
end | end | ||
if claims then | if claims then | ||
return getValue(claims, ", ") | return getValue(entity, claims, propertyID, ", ") | ||
else | else | ||
return "" | return "" | ||
Line 585: | Line 584: | ||
local input_parm = mw.text.trim(frame.args[3] or "") | local input_parm = mw.text.trim(frame.args[3] or "") | ||
if input_parm == "FETCH_WIKIDATA" then | if input_parm == "FETCH_WIKIDATA" then | ||
local | local entity = mw.wikibase.getEntity() | ||
if | if entity.claims[propertyID] ~= nil then | ||
local out = {} | local out = {} | ||
for k, v in pairs(entity.claims[propertyID]) do | |||
for k2, v2 in pairs(v.qualifiers[qualifierID]) do | |||
for k2, v2 in pairs( | |||
if v2.snaktype == 'value' then | if v2.snaktype == 'value' then | ||
out[#out + 1] = outputHook(v2); | out[#out + 1] = outputHook(v2); | ||
end | end | ||
end | end | ||
end | end | ||
return table.concat(out, ", "), true | return table.concat(out, ", "), true | ||
Line 619: | Line 616: | ||
-- This is used to get a value like 'male' (for property p21) which won't be linked and numbers without the thousand separators | -- 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) | p.getRawValue = function(frame) | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims, propertyID = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local | local entity = errorOrentity | ||
local | 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 | end | ||
return | return result | ||
end | end | ||
-- This is used to get the unit name for the numeric value returned by getRawValue | -- This is used to get the unit name for the numeric value returned by getRawValue | ||
p.getUnits = function(frame) | p.getUnits = function(frame) | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims, propertyID = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local | local entity = errorOrentity | ||
local | 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 | end | ||
return result | return result | ||
Line 660: | Line 646: | ||
-- This is used to get the unit's QID to use with the numeric value returned by getRawValue | -- This is used to get the unit's QID to use with the numeric value returned by getRawValue | ||
p.getUnitID = function(frame) | p.getUnitID = function(frame) | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local entity = errorOrentity | |||
local result | local result | ||
if isType(claims | if isType(claims, "quantity") then | ||
-- get the url for the unit entry on Wikidata: | -- get the url for the unit entry on Wikidata: | ||
result = claims[1].mainsnak.datavalue.value.unit | result = claims[1].mainsnak.datavalue.value.unit | ||
Line 696: | Line 683: | ||
local date_format = mw.text.trim(frame.args[3] or i18n["datetime"]["default-format"]) | 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 date_addon = mw.text.trim(frame.args[4] or i18n["datetime"]["default-addon"]) | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local entity = errorOrentity | |||
local out = {} | local out = {} | ||
for k, v in pairs(claims) do | |||
if v.mainsnak.datavalue.type == 'time' then | |||
if | local timestamp = v.mainsnak.datavalue.value.time | ||
local timestamp = | local dateprecision = v.mainsnak.datavalue.value.precision | ||
local dateprecision = | |||
-- A year can be stored like this: "+1872-00-00T00:00:00Z", | -- 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", | -- which is processed here as if it were the day before "+1872-01-01T00:00:00Z", | ||
Line 712: | Line 699: | ||
timestamp = timestamp:gsub("%-00%-00T", "-01-01T") | timestamp = timestamp:gsub("%-00%-00T", "-01-01T") | ||
out[#out + 1] = parseDateFull(timestamp, dateprecision, date_format, date_addon) | out[#out + 1] = parseDateFull(timestamp, dateprecision, date_format, date_addon) | ||
end | end | ||
end | end | ||
Line 736: | Line 722: | ||
local sep = mw.text.trim(frame.args[3] or " ") | local sep = mw.text.trim(frame.args[3] or " ") | ||
local imgsize = mw.text.trim(frame.args[4] or "frameless") | local imgsize = mw.text.trim(frame.args[4] or "frameless") | ||
local go, claims = parseInput(frame) | local go, errorOrentity, claims = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local entity = errorOrentity | |||
if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then | if (claims[1] and claims[1].mainsnak.datatype == "commonsMedia") then | ||
local out = {} | local out = {} | ||
for k, v in pairs(claims) do | |||
local filename = v.mainsnak.datavalue.value | |||
local filename = | |||
out[#out + 1] = "[[File:" .. filename .. "|" .. imgsize .. "]]" | out[#out + 1] = "[[File:" .. filename .. "|" .. imgsize .. "]]" | ||
end | end | ||
return table.concat(out, sep) | return table.concat(out, sep) | ||
Line 755: | Line 740: | ||
-- This is used to get the TA98 (Terminologia Anatomica first edition 1998) values like 'A01.1.00.005' (property P1323) | -- 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 | -- which are then linked to https://ifaa.unifr.ch/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 | -- 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 | -- 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) | p.getTAValue = function(frame) | ||
local | local ent = mw.wikibase.getEntity() | ||
local props = | local props = ent:formatPropertyValues('P1323') | ||
local out = {} | local out = {} | ||
local t = {} | local t = {} | ||
Line 767: | Line 752: | ||
t = mw.text.split( v, ", ") | t = mw.text.split( v, ", ") | ||
for k2, v2 in pairs(t) do | for k2, v2 in pairs(t) do | ||
out[#out + 1] = "[ | out[#out + 1] = "[https://ifaa.unifr.ch/Public/EntryPage/TA98%20Tree/Entity%20TA98%20EN/" .. string.sub(v2, 2) .. "%20Entity%20TA98%20EN.htm " .. v2 .. "]" | ||
end | end | ||
end | end | ||
Line 813: | Line 798: | ||
local input_parm = mw.text.trim(frame.args[1] or "") | local input_parm = mw.text.trim(frame.args[1] or "") | ||
if input_parm == "FETCH_WIKIDATA" then | if input_parm == "FETCH_WIKIDATA" then | ||
local ent = mw.wikibase.getEntity(id) | |||
local imgs | |||
if ent and ent.claims then | |||
imgs = ent.claims.P18 | |||
end | |||
local imglbl | local imglbl | ||
if | if imgs then | ||
-- look for an image with 'preferred' rank | |||
for k1, v1 in pairs(imgs) do | |||
imglbl = | 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 | end | ||
return imglbl | return imglbl | ||
else | else | ||
Line 834: | Line 843: | ||
p.getPropertyIDs = function(frame) | p.getPropertyIDs = function(frame) | ||
local go, propclaims = parseInput(frame) | local go, errorOrentity, propclaims = parseInput(frame) | ||
if not go then | if not go then | ||
return | return errorOrentity | ||
end | end | ||
local entity = errorOrentity | |||
-- if wiki-linked value collect the QID in a table | -- 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 | if (propclaims[1] and propclaims[1].mainsnak.snaktype == "value" and propclaims[1].mainsnak.datavalue.type == "wikibase-entityid") then | ||
local out = {} | local out = {} | ||
for k, v in pairs(propclaims) do | |||
out[#out + 1] = "Q" .. v.mainsnak.datavalue.value["numeric-id"] | |||
out[#out + 1] = "Q" .. | |||
end | end | ||
return table.concat(out, ", ") | return table.concat(out, ", ") | ||
Line 860: | Line 868: | ||
function p.claim(frame) | function p.claim(frame) | ||
local property = frame.args[1] or "" | local property = frame.args[1] or "" | ||
local id = frame.args["id"] | local id = frame.args["id"] | ||
local qualifierId = frame.args["qualifier"] | local qualifierId = frame.args["qualifier"] | ||
local parameter = frame.args["parameter"] | local parameter = frame.args["parameter"] | ||
Line 869: | Line 877: | ||
if default then showerrors = nil end | if default then showerrors = nil end | ||
-- | -- get wikidata entity | ||
local entity = mw.wikibase.getEntity(id) | |||
if not entity then | |||
if showerrors then return printError("entity-not-found") else return default end | if showerrors then return printError("entity-not-found") else return default end | ||
end | end | ||
-- fetch the first claim of satisfying the given property | -- fetch the first claim of satisfying the given property | ||
local claims = | local claims = findClaims(entity, property) | ||
if not claims or not claims[1] then | if not claims or not claims[1] then | ||
if showerrors then return printError("property-not-found") else return default end | if showerrors then return printError("property-not-found") else return default end | ||
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 result | ||
local error | local error | ||
if list then | if list then | ||
local value | local value | ||
Line 890: | Line 909: | ||
result = {} | result = {} | ||
for idx in pairs(claims) do | for idx in pairs(claims) do | ||
local claim = claims[ | local claim = claims[sortindices[idx]] | ||
value, error = getValueOfClaim(claim, qualifierId, parameter) | value, error = getValueOfClaim(claim, qualifierId, parameter) | ||
if not value and showerrors then value = error end | if not value and showerrors then value = error end | ||
if value and references then value = value .. getReferences(frame, claim) end | if value and references then value = value .. getReferences(frame, claim) end | ||
result[#result + 1] = value | result[#result + 1] = value | ||
end | end | ||
result = table.concat(result, list) | result = table.concat(result, list) | ||
else | else | ||
-- return first element | -- return first element | ||
local claim = claims[ | local claim = claims[sortindices[1]] | ||
result, error = getValueOfClaim(claim, qualifierId, parameter) | result, error = getValueOfClaim(claim, qualifierId, parameter) | ||
if result and references then result = result .. getReferences(frame, claim) end | if result and references then result = result .. getReferences(frame, claim) end | ||
Line 918: | Line 936: | ||
end | end | ||
local data = mw.wikibase.getEntity(id) | local data = mw.wikibase.getEntity(id) | ||
if not | if not data then | ||
return nil | return nil | ||
end | end | ||
Line 948: | Line 966: | ||
if qid == "" then qid = nil end | if qid == "" then qid = nil end | ||
local f = mw.text.trim( frame.args[1] or "") | local f = mw.text.trim( frame.args[1] or "") | ||
local entity = mw.wikibase.getEntity(qid) | |||
if not entity then | |||
return | return | ||
end | end | ||
local link = | local link = entity:getSitelink( f ) | ||
if not link then | if not link then | ||
return | return |