Module:WikidataIB: Difference between revisions
hide pen icon for unconfirmed users |
Richardpruen (talk | contribs) m 1 revision imported: templates |
||
(9 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
-- Version: | -- Version: 2023-07-10 | ||
-- Module to implement use of a blacklist and whitelist for infobox fields | -- Module to implement use of a blacklist and whitelist for infobox fields | ||
-- Can take a named parameter |qid which is the Wikidata ID for the article | -- Can take a named parameter |qid which is the Wikidata ID for the article | ||
Line 11: | Line 11: | ||
-- whitelist is passed in named parameter |fetchwikidata (or |fwd) | -- whitelist is passed in named parameter |fetchwikidata (or |fwd) | ||
require("strict") | |||
local p = {} | local p = {} | ||
local cdate -- initialise as nil and only load _complex_date function if needed | local cdate -- initialise as nil and only load _complex_date function if needed | ||
-- | -- Module:Complex date is loaded lazily and has the following dependencies: | ||
-- Module: | -- Module:Calendar | ||
-- Module: | -- Module:ISOdate | ||
-- Module:DateI18n | |||
-- Module:I18n/complex date | |||
-- Module:Ordinal | |||
-- Module:I18n/ordinal | |||
-- Module:Yesno | |||
-- Module:Formatnum | |||
-- Module:Linguistic | |||
-- | |||
-- The following, taken from https://www.mediawiki.org/wiki/Wikibase/DataModel#Dates_and_times, | -- The following, taken from https://www.mediawiki.org/wiki/Wikibase/DataModel#Dates_and_times, | ||
-- is needed to use Module:Complex date which seemingly requires date precision as a string. | -- is needed to use Module:Complex date which seemingly requires date precision as a string. | ||
Line 151: | Line 160: | ||
langobj = mw.language.new( langcode ) | langobj = mw.language.new( langcode ) | ||
else | else | ||
langcode = mw.getCurrentFrame(): | langcode = mw.getCurrentFrame():callParserFunction('int', {'lang'}) | ||
if mw.language.isKnownLanguageTag(langcode) then | if mw.language.isKnownLanguageTag(langcode) then | ||
langobj = mw.language.new( langcode ) | langobj = mw.language.new( langcode ) | ||
Line 567: | Line 576: | ||
-- uselbl is boolean switch to force display of the label instead of the sitelink (default: false) | -- uselbl is boolean switch to force display of the label instead of the sitelink (default: false) | ||
-- linkredir is boolean switch to allow linking to a redirect (default: false) | -- linkredir is boolean switch to allow linking to a redirect (default: false) | ||
-- formatvalue is boolean switch to allow formatting as italics or quoted (default: false) | |||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
-- Dependencies: labelOrId(); donotlink[] | -- Dependencies: labelOrId(); donotlink[] | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
local linkedItem = function(id, args) | local linkedItem = function(id, args) | ||
local lprefix = args.lprefix or "" -- toughen against nil values passed | local lprefix = (args.lp or args.lprefix or args.linkprefix or ""):gsub('"', '') -- toughen against nil values passed | ||
local lpostfix = args.lpostfix or "" | local lpostfix = (args.lpostfix or ""):gsub('"', '') | ||
local prefix = args.prefix or "" | local prefix = (args.prefix or ""):gsub('"', '') | ||
local postfix = args.postfix or "" | local postfix = (args.postfix or ""):gsub('"', '') | ||
local dtxt = args.dtxt | local dtxt = args.dtxt | ||
local shortname = args.shortname | local shortname = args.shortname or args.sn | ||
local lang = args.lang or "en" -- fallback to default if missing | local lang = args.lang or "en" -- fallback to default if missing | ||
local uselbl = args.uselabel or args.uselbl | local uselbl = args.uselabel or args.uselbl | ||
Line 582: | Line 592: | ||
local linkredir = args.linkredir | local linkredir = args.linkredir | ||
linkredir = parseParam(linkredir, false) | linkredir = parseParam(linkredir, false) | ||
local formatvalue = args.formatvalue or args.fv | |||
formatvalue = parseParam(formatvalue, false) | |||
-- see if item might need italics or quotes | -- see if item might need italics or quotes | ||
local fmt = "" | local fmt = "" | ||
if next(formats) then | if next(formats) and formatvalue then | ||
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P31") ) do | for k, v in ipairs( mw.wikibase.getBestStatements(id, "P31") ) do | ||
if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then | if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then | ||
Line 1,268: | Line 1,280: | ||
args.pd = pd | args.pd = pd | ||
-- allow qualifiers to have a different date format; default to year | -- allow qualifiers to have a different date format; default to year unless qualsonly is set | ||
args.qdf = args.qdf or args.qualifierdateformat or args.df or "y" | args.qdf = args.qdf or args.qualifierdateformat or args.df or (not qualsonly and "y") | ||
local lang = args.lang or | local lang = args.lang or findLang().code | ||
-- qualID is a string list of wanted qualifiers or "ALL" | -- qualID is a string list of wanted qualifiers or "ALL" | ||
Line 1,396: | Line 1,408: | ||
elseif t ~= "" then | elseif t ~= "" then | ||
if qualsonly then | if qualsonly then | ||
out[#out+1] = timestart .. dsep .. timeend | if timestart == "" then | ||
out[#out+1] = timeend | |||
elseif timeend == "" then | |||
out[#out+1] = timestart | |||
else | |||
out[#out+1] = timestart .. dsep .. timeend | |||
end | |||
else | else | ||
out[#out] = out[#out] .. " (" .. timestart .. dsep .. timeend .. ")" | out[#out] = out[#out] .. " (" .. timestart .. dsep .. timeend .. ")" | ||
Line 1,476: | Line 1,494: | ||
local uabbr = parseParam(args.unitabbr or args.uabbr, false) | local uabbr = parseParam(args.unitabbr or args.uabbr, false) | ||
local filter = (args.unit or ""):upper() | local filter = (args.unit or ""):upper() | ||
local maxvals = tonumber(args.maxvals) or 0 | |||
if filter == "" then filter = nil end | if filter == "" then filter = nil end | ||
Line 1,507: | Line 1,526: | ||
return nil | return nil | ||
end -- of check for string | end -- of check for string | ||
if maxvals > 0 and #out >= maxvals then break end | |||
end -- of loop through values of propertyID | end -- of loop through values of propertyID | ||
return assembleoutput(out, frame.args, qid, propertyID) | return assembleoutput(out, frame.args, qid, propertyID) | ||
Line 1,549: | Line 1,569: | ||
end | end | ||
for i2, v2 in ipairs(proptbl) do | for i2, v2 in ipairs(proptbl) do | ||
parttbl = v2.qualifiers and v2.qualifiers.P518 | local parttbl = v2.qualifiers and v2.qualifiers.P518 | ||
if parttbl then | if parttbl then | ||
-- this higher location has qualifier 'applies to part' (P518) | -- this higher location has qualifier 'applies to part' (P518) | ||
Line 1,581: | Line 1,601: | ||
if #inst > 0 then | if #inst > 0 then | ||
for k, v in ipairs(inst) do | for k, v in ipairs(inst) do | ||
local instid = v.mainsnak.datavalue.value.id | local instid = v.mainsnak.datavalue and v.mainsnak.datavalue.value.id | ||
-- stop if it's a country (or a country within the United Kingdom if skip is true) | -- stop if it's a country (or a country within the United Kingdom if skip is true) | ||
if instid == "Q6256" or instid == "Q3624078" or (skip and instid == "Q3336843") then | if instid == "Q6256" or instid == "Q3624078" or (skip and instid == "Q3336843") then | ||
Line 1,895: | Line 1,915: | ||
-- whose value is to be returned is passed in named parameter |qual= | -- whose value is to be returned is passed in named parameter |qual= | ||
local qualifierID = frame.args.qual | local qualifierID = frame.args.qual | ||
-- A filter can be set like this: filter=P642==Q22674854 | |||
local filter, fprop, fval | |||
local ftable = mw.text.split(frame.args.filter or "", "==") | |||
if ftable[2] then | |||
fprop = mw.text.trim(ftable[1]) | |||
fval = mw.text.trim(ftable[2]) | |||
filter = true | |||
end | |||
-- onlysourced is a boolean passed to return qualifiers | -- onlysourced is a boolean passed to return qualifiers | ||
Line 1,920: | Line 1,949: | ||
for k1, v1 in pairs(props) do | for k1, v1 in pairs(props) do | ||
if v1.mainsnak.snaktype == "value" and v1.mainsnak.datavalue.type == "wikibase-entityid" then | if v1.mainsnak.snaktype == "value" and v1.mainsnak.datavalue.type == "wikibase-entityid" then | ||
-- It's a wiki-linked value, so check if it's the target (in propvalue) | -- It's a wiki-linked value, so check if it's the target (in propvalue) and if it has qualifiers | ||
if v1.mainsnak.datavalue.value.id == propvalue and v1.qualifiers then | if v1.mainsnak.datavalue.value.id == propvalue and v1.qualifiers then | ||
if onlysrc == false or sourced(v1) then | if onlysrc == false or sourced(v1) then | ||
-- if we've got this far, we have a (sourced) claim with qualifiers | -- if we've got this far, we have a (sourced) claim with qualifiers | ||
-- which matches the target, so find the value(s) of the qualifier we want | -- which matches the target, so apply the filter and find the value(s) of the qualifier we want | ||
local quals = v1.qualifiers[qualifierID] | if not filter or (v1.qualifiers[fprop] and v1.qualifiers[fprop][1].datavalue.value.id == fval) then | ||
local quals = v1.qualifiers[qualifierID] | |||
if quals then | |||
-- can't reference qualifer, so set onlysourced = "no" (args are strings, not boolean) | |||
local qargs = frame.args | |||
qargs.onlysourced = "no" | |||
local vals = propertyvalueandquals(quals, qargs, qid) | |||
for k, v in ipairs(vals) do | |||
out[#out + 1] = v | |||
end | |||
end | end | ||
end | end | ||
Line 2,116: | Line 2,146: | ||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; | -- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
p. | p._getPropertyIDs = function(args) | ||
args.reqranks = setRanks(args.rank) | args.reqranks = setRanks(args.rank) | ||
args.langobj = findLang(args.lang) | args.langobj = findLang(args.lang) | ||
Line 2,134: | Line 2,163: | ||
local maxvals = tonumber(args.maxvals) or 0 | local maxvals = tonumber(args.maxvals) or 0 | ||
out = {} | local out = {} | ||
for i, v in ipairs(props) do | for i, v in ipairs(props) do | ||
local snak = v.mainsnak | local snak = v.mainsnak | ||
Line 2,148: | Line 2,177: | ||
return assembleoutput(out, args, qid, pid) | return assembleoutput(out, args, qid, pid) | ||
end | |||
p.getPropertyIDs = function(frame) | |||
local args = frame.args | |||
return p._getPropertyIDs(args) | |||
end | end | ||
Line 2,183: | Line 2,217: | ||
qlist = qlist:gsub("[%p%s]+", " ") .. " " | qlist = qlist:gsub("[%p%s]+", " ") .. " " | ||
out = {} | local out = {} | ||
for i, v in ipairs(props) do | for i, v in ipairs(props) do | ||
local snak = v.mainsnak | local snak = v.mainsnak | ||
Line 2,243: | Line 2,277: | ||
local pid1 = args.prop1 or args.pid1 or "" | local pid1 = args.prop1 or args.pid1 or "" | ||
local pid2 = args.prop2 or args.pid2 or "" | local pid2 = args.prop2 or args.pid2 or "" | ||
if pid1 == "" or pid2 == "" then return nil end | if pid1 == "" or pid2 == "" then return nil end | ||
local f = {} | local f = {} | ||
f.args = args | f.args = args | ||
local qid1, statements1 = parseInput(f, | local qid1, statements1 = parseInput(f, args[1], pid1) | ||
if not qid1 then return | -- parseInput nulls empty args[1] and returns args[1] if nothing on Wikidata | ||
if not qid1 then return statements1 end | |||
-- otherwise it returns the qid and a table for the statement | |||
local onlysrc = parseParam(args.onlysourced or args.osd, true) | local onlysrc = parseParam(args.onlysourced or args.osd, true) | ||
local maxvals = tonumber(args.maxvals) or 0 | local maxvals = tonumber(args.maxvals) or 0 | ||
Line 2,466: | Line 2,500: | ||
if maxvals > 0 and #cat2 >= maxvals then break end | if maxvals > 0 and #cat2 >= maxvals then break end | ||
end | end | ||
out = {} | local out = {} | ||
for k1, v1 in ipairs(cat1) do | for k1, v1 in ipairs(cat1) do | ||
for k2, v2 in ipairs(cat2) do | for k2, v2 in ipairs(cat2) do | ||
Line 2,958: | Line 2,992: | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
-- followQid takes | -- followQid takes four optional parameters: qid, props, list and all. | ||
-- If qid is not given, it uses the qid for the connected page | -- If qid is not given, it uses the qid for the connected page | ||
-- or returns nil if there isn't one. | -- or returns nil if there isn't one. | ||
Line 2,964: | Line 2,998: | ||
-- If props is given, the Wikidata item for the qid is examined for each property in turn. | -- If props is given, the Wikidata item for the qid is examined for each property in turn. | ||
-- If that property contains a value that is another Wikibase-item, that item's qid is returned, | -- If that property contains a value that is another Wikibase-item, that item's qid is returned, | ||
-- and the search terminates, unless |all=y when all of the qids are returned, | -- and the search terminates, unless |all=y when all of the qids are returned, separated by spaces. | ||
-- If |list= is set to a template, the qids are passed as arguments to the template. | |||
-- If props is not given, the qid is returned. | -- If props is not given, the qid is returned. | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
Line 2,972: | Line 3,007: | ||
local qid = (args.qid or ""):upper() | local qid = (args.qid or ""):upper() | ||
local all = parseParam(args.all, false) | local all = parseParam(args.all, false) | ||
local list = args.list or "" | |||
if list == "" then list = nil end | |||
if qid == "" then | if qid == "" then | ||
qid = mw.wikibase.getEntityIdForCurrentPage() | qid = mw.wikibase.getEntityIdForCurrentPage() | ||
Line 2,994: | Line 3,031: | ||
end | end | ||
if #out > 0 then | if #out > 0 then | ||
local ret = "" | |||
if list then | |||
ret = mw.getCurrentFrame():expandTemplate{title = list, args = out} | |||
else | |||
ret = table.concat(out, " ") | |||
end | |||
return ret | |||
else | else | ||
return qid | return qid | ||
Line 3,024: | Line 3,067: | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
p.siteID = function(frame) | p.siteID = function(frame) | ||
local txtlang = frame: | local txtlang = frame:callParserFunction('int', {'lang'}) or "" | ||
-- This deals with specific exceptions: be-tarask -> be-x-old | -- This deals with specific exceptions: be-tarask -> be-x-old | ||
if txtlang == "be-tarask" then | if txtlang == "be-tarask" then | ||
Line 3,048: | Line 3,091: | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
p.projID = function(frame) | p.projID = function(frame) | ||
local txtlang = frame: | local txtlang = frame:callParserFunction('int', {'lang'}) or "" | ||
-- This deals with specific exceptions: be-tarask -> be-x-old | -- This deals with specific exceptions: be-tarask -> be-x-old | ||
if txtlang == "be-tarask" then | if txtlang == "be-tarask" then | ||
Line 3,141: | Line 3,184: | ||
if qid:sub(1,1) ~= "Q" then qid = mw.wikibase.getEntityIdForCurrentPage() end | if qid:sub(1,1) ~= "Q" then qid = mw.wikibase.getEntityIdForCurrentPage() end | ||
if not qid then return nil end | if not qid then return nil end | ||
ranks = setRanks(args.rank) | local ranks = setRanks(args.rank) | ||
local stats = {} | local stats = {} | ||
if ranks.b then | if ranks.b then | ||
Line 3,151: | Line 3,194: | ||
if stats[1].mainsnak.datatype == "wikibase-item" then | if stats[1].mainsnak.datatype == "wikibase-item" then | ||
for k, v in pairs( stats ) do | for k, v in pairs( stats ) do | ||
ms = v.mainsnak | local ms = v.mainsnak | ||
if ranks[v.rank:sub(1,1)] and ms.snaktype == "value" and ms.datavalue.value.id == val then | if ranks[v.rank:sub(1,1)] and ms.snaktype == "value" and ms.datavalue.value.id == val then | ||
return val | return val | ||
Line 3,207: | Line 3,250: | ||
local url = frame.args.url or "" | local url = frame.args.url or "" | ||
if url:upper() == "NONE" then return nil end | if url:upper() == "NONE" then return nil end | ||
local urls = {} | |||
local quals = {} | |||
local qid = frame.args.qid or "" | local qid = frame.args.qid or "" | ||
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end | if url and url ~= "" then | ||
urls[1] = url | |||
else | |||
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end | |||
if not qid then return nil end | |||
local prop856 = mw.wikibase.getBestStatements(qid, "P856") | local prop856 = mw.wikibase.getBestStatements(qid, "P856") | ||
for k, v in pairs(prop856) do | for k, v in pairs(prop856) do | ||
Line 3,228: | Line 3,272: | ||
end -- test for website having a value | end -- test for website having a value | ||
end -- loop through website(s) | end -- loop through website(s) | ||
end | end | ||
if #urls == 0 then return nil end | if #urls == 0 then return nil end | ||
Line 3,389: | Line 3,431: | ||
local site = args.site or "" | local site = args.site or "" | ||
local showdab = parseParam(args.showdab, true) | local showdab = parseParam(args.showdab, true) | ||
qid = mw.wikibase.getEntityIdForTitle(title, site) | local qid = mw.wikibase.getEntityIdForTitle(title, site) | ||
if qid then | if qid then | ||
local prop31 = mw.wikibase.getBestStatements(qid, "P31")[1] | local prop31 = mw.wikibase.getBestStatements(qid, "P31")[1] |