| Line 1: |
Line 1: |
| | + | -- Version: 2021-02-06 |
| | -- 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 13: |
Line 14: |
| | | | |
| | 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:Complex date is loaded lazily and has the following dependencies: |
| − | -- Module:I18n/complex date, Module:ISOdate, Module:DateI18n (alternative for Module:Date), | + | -- Module:Calendar |
| − | -- Module:Formatnum, Module:I18n/date, Module:Yesno, Module:Linguistic, Module:Calendar | + | -- Module:ISOdate |
| | + | -- Module:DateI18n |
| | + | -- Module:No globals |
| | + | -- 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 564: |
Line 574: |
| | -- shortname is boolean switch to use P1813 (short name) instead of label if true. | | -- shortname is boolean switch to use P1813 (short name) instead of label if true. |
| | -- lang is the current language code. | | -- lang is the current language code. |
| | + | -- 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) |
| | + | -- formatvalue is boolean switch to allow formatting as italics or quoted (default: false) |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: labelOrId(); donotlink[] | | -- Dependencies: labelOrId(); donotlink[] |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | local linkedItem = function(id, lprefix, lpostfix, prefix, postfix, dtxt, shortname, lang) | + | local linkedItem = function(id, args) |
| − | lprefix = lprefix or "" -- toughen against nil values passed | + | local lprefix = (args.lp or args.lprefix or args.linkprefix or ""):gsub('"', '') -- toughen against nil values passed |
| − | lpostfix = lpostfix or "" | + | local lpostfix = (args.lpostfix or ""):gsub('"', '') |
| − | prefix = prefix or "" | + | local prefix = (args.prefix or ""):gsub('"', '') |
| − | postfix = postfix or "" | + | local postfix = (args.postfix or ""):gsub('"', '') |
| − | lang = lang or "en" -- fallback to default if missing | + | local dtxt = args.dtxt |
| | + | local shortname = args.shortname |
| | + | local lang = args.lang or "en" -- fallback to default if missing |
| | + | local uselbl = args.uselabel or args.uselbl |
| | + | uselbl = parseParam(uselbl, false) |
| | + | local linkredir = args.linkredir |
| | + | 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 = "" |
| − | for k, v in ipairs( mw.wikibase.getBestStatements(id, "P31") ) do | + | if next(formats) and formatvalue then |
| − | if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then
| + | for k, v in ipairs( mw.wikibase.getBestStatements(id, "P31") ) do |
| − | fmt = formats[v.mainsnak.datavalue.value.id]
| + | if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then |
| − | break -- pick the first match
| + | fmt = formats[v.mainsnak.datavalue.value.id] |
| | + | break -- pick the first match |
| | + | end |
| | end | | end |
| | end | | end |
| Line 605: |
Line 628: |
| | if sitelink then | | if sitelink then |
| | if not (dtxt or shortname) then | | if not (dtxt or shortname) then |
| − | -- strip any namespace or dab from the sitelink | + | -- if sitelink and label are the same except for case, no need to process further |
| − | local pos = sitelink:find(":") or 0
| + | if sitelink:lower() ~= label:lower() then |
| − | local slink = sitelink
| + | -- strip any namespace or dab from the sitelink |
| − | if pos > 0 then
| + | local pos = sitelink:find(":") or 0 |
| − | local prefix = sitelink:sub(1,pos-1)
| + | local slink = sitelink |
| − | if mw.site.namespaces[prefix] then -- that prefix is a valid namespace, so remove it
| + | if pos > 0 then |
| − | slink = sitelink:sub(pos+1)
| + | local pfx = sitelink:sub(1,pos-1) |
| | + | if mw.site.namespaces[pfx] then -- that prefix is a valid namespace, so remove it |
| | + | slink = sitelink:sub(pos+1) |
| | + | end |
| | + | end |
| | + | -- remove stuff after commas or inside parentheses - ie. dabs |
| | + | slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "") |
| | + | -- if uselbl is false, use sitelink instead of label |
| | + | if not uselbl then |
| | + | -- use slink as display, preserving label case - find("^%u") is true for 1st char uppercase |
| | + | if label:find("^%u") then |
| | + | label = slink:gsub("^(%l)", string.upper) |
| | + | else |
| | + | label = slink:gsub("^(%u)", string.lower) |
| | + | end |
| | end | | end |
| − | end
| |
| − | -- remove stuff after commas or inside parentheses - ie. dabs
| |
| − | slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "")
| |
| − | -- use that as label, preserving label case - find("^%u") is true for 1st char uppercase
| |
| − | if label:find("^%u") then
| |
| − | label = slink:gsub("^(%l)", string.upper)
| |
| − | else
| |
| − | label = slink:gsub("^(%u)", string.lower)
| |
| | end | | end |
| | end | | end |
| Line 629: |
Line 658: |
| | end | | end |
| | elseif islabel then | | elseif islabel then |
| − | -- no sitelink, label exists, so check if a redirect with that title exists | + | -- no sitelink, label exists, so check if a redirect with that title exists, if linkredir is true |
| − | local artitle = mw.title.new(label, 0) -- only nil if label has invalid chars | + | -- display plain label by default |
| − | if not donotlink[label] and artitle and artitle.redirectTarget then
| + | disp = prefix .. fmt .. label .. fmt .. postfix |
| − | -- there's a redirect with the same title as the label, so let's link to that
| + | if linkredir then |
| − | disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]"
| + | local artitle = mw.title.new(label, 0) -- only nil if label has invalid chars |
| − | else
| + | if not donotlink[label] and artitle and artitle.redirectTarget then |
| − | -- either (donotlink is true) or (no sitelink, label exists, not redirect) | + | -- there's a redirect with the same title as the label, so let's link to that |
| − | -- so output unlinked label with italics or quotes as needed
| + | disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]" |
| − | disp = prefix .. fmt .. label .. fmt .. postfix
| + | end |
| | end -- test if article title exists as redirect on current Wiki | | end -- test if article title exists as redirect on current Wiki |
| | else | | else |
| Line 794: |
Line 823: |
| | -- createicon assembles the "Edit at Wikidata" pen icon. | | -- createicon assembles the "Edit at Wikidata" pen icon. |
| | -- It returns a wikitext string inside a span class="penicon" | | -- It returns a wikitext string inside a span class="penicon" |
| | + | -- if entityID is nil or empty, the ID associated with current page is used |
| | + | -- langcode and propertyID may be nil or empty |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: i18n[]; | | -- Dependencies: i18n[]; |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | local createicon = function(langcode, entityID, propertyID) | | local createicon = function(langcode, entityID, propertyID) |
| − | local icon = " <span class='penicon'>[[" | + | langcode = langcode or "" |
| | + | if not entityID or entityID == "" then entityID= mw.wikibase.getEntityIdForCurrentPage() end |
| | + | propertyID = propertyID or "" |
| | + | local icon = " <span class='penicon autoconfirmed-show'>[[" |
| | -- " <span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge | | -- " <span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge |
| | .. i18n["filespace"] | | .. i18n["filespace"] |
| Line 804: |
Line 838: |
| | .. i18n["editonwikidata"] | | .. i18n["editonwikidata"] |
| | .. "|link=https://www.wikidata.org/wiki/" .. entityID | | .. "|link=https://www.wikidata.org/wiki/" .. entityID |
| − | .. "?uselang=" .. langcode | + | if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end |
| − | if propertyID then icon = icon .. "#" .. propertyID end | + | if propertyID ~= "" then icon = icon .. "#" .. propertyID end |
| | icon = icon .. "|" .. i18n["editonwikidata"] .. "]]</span>" | | icon = icon .. "|" .. i18n["editonwikidata"] .. "]]</span>" |
| | return icon | | return icon |
| Line 814: |
Line 848: |
| | -- assembleoutput takes the sequence table containing the property values | | -- assembleoutput takes the sequence table containing the property values |
| | -- and formats it according to switches given. It returns a string or nil. | | -- and formats it according to switches given. It returns a string or nil. |
| − | -- It needs the entityID and propertyID to create a link in the pen icon. | + | -- It uses the entityID (and optionally propertyID) to create a link in the pen icon. |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: parseParam(); | | -- Dependencies: parseParam(); |
| Line 938: |
Line 972: |
| | local qnumber = dv.id | | local qnumber = dv.id |
| | if linked then | | if linked then |
| − | val = linkedItem(qnumber, lpre, lpost, pre, post, dtxt, shortname, args.lang) | + | val = linkedItem(qnumber, args) |
| | else -- no link wanted so check for display-text, otherwise test for lang code | | else -- no link wanted so check for display-text, otherwise test for lang code |
| | local label, islabel | | local label, islabel |
| Line 1,246: |
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 findlang().code | + | 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,374: |
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,454: |
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,485: |
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,527: |
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,554: |
Line 1,596: |
| | end | | end |
| | | | |
| − | -- check if it's an instance of (P31) a country (Q6256) and terminate the chain if it is | + | -- check if it's an instance of (P31) a country (Q6256) or sovereign state (Q3624078) |
| | + | -- and terminate the chain if it is |
| | local inst = mw.wikibase.getAllStatements(qid, "P31") | | local inst = mw.wikibase.getAllStatements(qid, "P31") |
| | 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 (skip and instid == "Q3336843") then | + | if instid == "Q6256" or instid == "Q3624078" or (skip and instid == "Q3336843") then |
| | prop = nil -- this will ensure this is treated as top-level location | | prop = nil -- this will ensure this is treated as top-level location |
| | break | | break |
| Line 1,570: |
Line 1,613: |
| | if prop and prop.mainsnak.datavalue then | | if prop and prop.mainsnak.datavalue then |
| | if not skip or count == 0 then | | if not skip or count == 0 then |
| − | out[#out+1] = linkedItem(qid, ":", "", "", "") -- get a linked value if we can | + | local args = { lprefix = ":" } |
| | + | out[#out+1] = linkedItem(qid, args) -- get a linked value if we can |
| | end | | end |
| | qid, prevqid = prop.mainsnak.datavalue.value.id, qid | | qid, prevqid = prop.mainsnak.datavalue.value.id, qid |
| Line 1,802: |
Line 1,846: |
| | -- getCoords is used to get coordinates for display in an infobox | | -- getCoords is used to get coordinates for display in an infobox |
| | -- whitelist and blacklist are implemented | | -- whitelist and blacklist are implemented |
| − | -- optional 'display' parameter is allowed, defaults to "inline, title" | + | -- optional 'display' parameter is allowed, defaults to nil - was "inline, title" |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: setRanks(); parseInput(); decimalPrecision(); | | -- Dependencies: setRanks(); parseInput(); decimalPrecision(); |
| Line 1,810: |
Line 1,854: |
| | | | |
| | -- if there is a 'display' parameter supplied, use it | | -- if there is a 'display' parameter supplied, use it |
| − | -- otherwise default to "inline, title" | + | -- otherwise default to nothing |
| | local disp = frame.args.display or "" | | local disp = frame.args.display or "" |
| | if disp == "" then | | if disp == "" then |
| − | disp = "inline, title" | + | disp = nil -- default to not supplying display parameter, was "inline, title" |
| | end | | end |
| | | | |
| Line 1,871: |
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,896: |
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 |
| − | -- 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 |
| − | if quals then
| + | local quals = v1.qualifiers[qualifierID] |
| − | -- can't reference qualifer, so set onlysourced = "no" (not boolean)
| + | if quals then |
| − | local qargs = frame.args
| + | -- can't reference qualifer, so set onlysourced = "no" (args are strings, not boolean) |
| − | qargs.onlysourced = "no"
| + | local qargs = frame.args |
| − | local vals = propertyvalueandquals(quals, qargs, qid)
| + | qargs.onlysourced = "no" |
| − | for k, v in ipairs(vals) do
| + | local vals = propertyvalueandquals(quals, qargs, qid) |
| − | out[#out + 1] = v
| + | for k, v in ipairs(vals) do |
| | + | out[#out + 1] = v |
| | + | end |
| | end | | end |
| | end | | end |
| Line 2,092: |
Line 2,146: |
| | -- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; | | -- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | p.getPropertyIDs = function(frame) | + | p._getPropertyIDs = function(args) |
| − | local args = frame.args
| |
| | args.reqranks = setRanks(args.rank) | | args.reqranks = setRanks(args.rank) |
| | args.langobj = findLang(args.lang) | | args.langobj = findLang(args.lang) |
| Line 2,110: |
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,124: |
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,159: |
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,193: |
Line 2,251: |
| | -- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; | | -- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | p.getPropOfProp = function(frame) | + | p._getPropOfProp = function(args) |
| − | frame.args.reqranks = setRanks(frame.args.rank) | + | -- parameter sets for commonly used groups of parameters |
| − | frame.args.langobj = findLang(frame.args.lang) | + | local paraset = tonumber(args.ps or args.parameterset or 0) |
| − | frame.args.lang = frame.args.langobj.code | + | if paraset == 1 then |
| − | local args = frame.args
| + | -- a common setting |
| − | local pid1 = args.prop1 or args.pid1 or "" | + | args.rank = "best" |
| | + | args.fetchwikidata = "ALL" |
| | + | args.onlysourced = "no" |
| | + | args.noicon = "true" |
| | + | elseif paraset == 2 then |
| | + | -- equivalent to raw |
| | + | args.rank = "best" |
| | + | args.fetchwikidata = "ALL" |
| | + | args.onlysourced = "no" |
| | + | args.noicon = "true" |
| | + | args.linked = "no" |
| | + | args.pd = "true" |
| | + | elseif paraset == 3 then |
| | + | -- third set goes here |
| | + | end |
| | + | |
| | + | args.reqranks = setRanks(args.rank) |
| | + | args.langobj = findLang(args.lang) |
| | + | args.lang = args.langobj.code |
| | + | local pid1 = args.prop1 or args.pid1 or "" |
| | local pid2 = args.prop2 or args.pid2 or "" | | local pid2 = args.prop2 or args.pid2 or "" |
| − | local localval = mw.text.trim(args[1] or "")
| |
| | if pid1 == "" or pid2 == "" then return nil end | | if pid1 == "" or pid2 == "" then return nil end |
| − | local qid1, statements1 = parseInput(frame, localval, pid1) | + | |
| − | if not qid1 then return localval end | + | local f = {} |
| | + | f.args = args |
| | + | local qid1, statements1 = parseInput(f, args[1], pid1) |
| | + | -- 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,229: |
Line 2,310: |
| | end -- of loop through values of property1 | | end -- of loop through values of property1 |
| | return assembleoutput(out, args, qid1, pid1) | | return assembleoutput(out, args, qid1, pid1) |
| | + | end |
| | + | |
| | + | p.getPropOfProp = function(frame) |
| | + | local args= frame.args |
| | + | if not args.prop1 and not args.pid1 then |
| | + | args = frame:getParent().args |
| | + | if not args.prop1 and not args.pid1 then return i18n.errors["No property supplied"] end |
| | + | end |
| | + | |
| | + | return p._getPropOfProp(args) |
| | end | | end |
| | | | |
| Line 2,409: |
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,493: |
Line 2,584: |
| | end | | end |
| | elseif qtype == "url" then | | elseif qtype == "url" then |
| − | qv = mw.wikibase.renderSnak(vqualifiers[v1][1]) | + | if vqualifiers[v1][1].snaktype == "value" then |
| − | local display = mw.ustring.match( mw.uri.decode(qv, "WIKI"), "([%w ]+)$" )
| + | qv = mw.wikibase.renderSnak(vqualifiers[v1][1]) |
| − | if display then
| + | local display = mw.ustring.match( mw.uri.decode(qv, "WIKI"), "([%w ]+)$" ) |
| − | qv = "[" .. qv .. " " .. display .. "]"
| + | if display then |
| | + | qv = "[" .. qv .. " " .. display .. "]" |
| | + | end |
| | end | | end |
| | else | | else |
| Line 2,691: |
Line 2,784: |
| | if not (whitelist == 'ALL' or whitelist:find(fieldname)) then return nil end | | if not (whitelist == 'ALL' or whitelist:find(fieldname)) then return nil end |
| | | | |
| − | local qid = mw.text.trim(args.qid or "") | + | local qid = args.qid or "" |
| − | if qid == "" then qid = nil end | + | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end |
| | + | if not qid or not mw.wikibase.entityExists(qid) then return nil end |
| | | | |
| − | local entity = mw.wikibase.getEntity(qid) | + | local aliases = mw.wikibase.getEntity(qid).aliases |
| − | if not entity then return nil end
| |
| − | local aliases = entity.aliases
| |
| | if not aliases then return nil end | | if not aliases then return nil end |
| − | if not qid then qid= mw.wikibase.getEntityIdForCurrentPage() end
| |
| | | | |
| | args.langobj = findLang(args.lang) | | args.langobj = findLang(args.lang) |
| Line 2,901: |
Line 2,992: |
| | | | |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | -- followQid takes three optional parameters: qid, props, and all. | + | -- 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,907: |
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, sparated by spaces. | + | -- 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. |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: parseParam() | | -- Dependencies: parseParam() |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | p.followQid = function(frame) | + | p._followQid = function(args) |
| − | local qid = (frame.args.qid or ""):upper() | + | local qid = (args.qid or ""):upper() |
| − | local all = parseParam(frame.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,920: |
Line 3,014: |
| | if not qid then return nil end | | if not qid then return nil end |
| | local out = {} | | local out = {} |
| − | local props = (frame.args.props or ""):upper() | + | local props = (args.props or ""):upper() |
| | if props ~= "" then | | if props ~= "" then |
| | for p in mw.text.gsplit(props, "%p") do -- split at punctuation and iterate | | for p in mw.text.gsplit(props, "%p") do -- split at punctuation and iterate |
| Line 2,937: |
Line 3,031: |
| | end | | end |
| | if #out > 0 then | | if #out > 0 then |
| − | return table.concat(out, " ") | + | 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 |
| | end | | end |
| | + | end |
| | + | |
| | + | p.followQid = function(frame) |
| | + | return p._followQid(frame.args) |
| | end | | end |
| | | | |
| Line 3,056: |
Line 3,160: |
| | -- from the item given by the parameter 'qid' | | -- from the item given by the parameter 'qid' |
| | -- or from the Wikidata item associated with the current page if qid is not supplied. | | -- or from the Wikidata item associated with the current page if qid is not supplied. |
| | + | -- It only checks ranks that are requested (preferred and normal by default) |
| | -- If property is not supplied, then P31 (instance of) is assumed. | | -- If property is not supplied, then P31 (instance of) is assumed. |
| | -- It returns val if found or nothing if not found. | | -- It returns val if found or nothing if not found. |
| Line 3,079: |
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 |
| − | local stats = mw.wikibase.getAllStatements( qid, pid ) | + | local ranks = setRanks(args.rank) |
| | + | local stats = {} |
| | + | if ranks.b then |
| | + | stats = mw.wikibase.getBestStatements(qid, pid) |
| | + | else |
| | + | stats = mw.wikibase.getAllStatements( qid, pid ) |
| | + | end |
| | if not stats[1] then return nil end | | if not stats[1] then return nil end |
| | 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 |
| − | if v.mainsnak.snaktype == "value" and v.mainsnak.datavalue.value.id == val then | + | local ms = v.mainsnak |
| | + | if ranks[v.rank:sub(1,1)] and ms.snaktype == "value" and ms.datavalue.value.id == val then |
| | return val | | return val |
| | end | | end |
| Line 3,098: |
Line 3,210: |
| | -- but it keeps the "edit at Wikidata" pen icon out of the microformat. | | -- but it keeps the "edit at Wikidata" pen icon out of the microformat. |
| | -- Usually it will take its url parameter directly from a Wikidata call: | | -- Usually it will take its url parameter directly from a Wikidata call: |
| − | -- e.g. {{#invoke:WikidataIB |url2 |url={{wdib |P856 |qid=Q23317 |fwd=ALL |osd=no}} | + | -- e.g. {{#invoke:WikidataIB |url2 |url={{wdib |P856 |qid=Q23317 |fwd=ALL |osd=no}} }} |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | -- Dependencies: none | | -- Dependencies: none |
| Line 3,105: |
Line 3,217: |
| | local txt = frame.args.url or "" | | local txt = frame.args.url or "" |
| | if txt == "" then return nil end | | if txt == "" then return nil end |
| | + | -- extract any icon |
| | local url, icon = txt:match("(.+) (.+)") | | local url, icon = txt:match("(.+) (.+)") |
| − | url = url or txt | + | -- make sure there's at least a space at the end |
| | + | url = (url or txt) .. " " |
| | icon = icon or "" | | icon = icon or "" |
| − | local prot, addr = url:match("(http[s]*://)(.+)") | + | -- extract any protocol like https:// |
| − | prot = prot or url | + | local prot = url:match("(https*://).+[ \"\']") |
| − | addr = addr or ""
| + | -- extract address |
| − | local disp, n = addr:gsub("%.", "<wbr/>%.") | + | local addr = "" |
| | + | if prot then |
| | + | addr = url:match("https*://(.+)[ \"\']") or " " |
| | + | else |
| | + | prot = "//" |
| | + | addr = url:match("[^%p%s]+%.(.+)[ \"\']") or " " |
| | + | end |
| | + | -- strip trailing / from end of domain-only url and add <wbr/> before . and / |
| | + | local disp, n = addr:gsub( "^([^/]+)/$", "%1" ):gsub("%/", "<wbr/>/"):gsub("%.", "<wbr/>.") |
| | return '<span class="url">[' .. prot .. addr .. " " .. disp .. "]</span> " .. icon | | return '<span class="url">[' .. prot .. addr .. " " .. disp .. "]</span> " .. icon |
| | end | | end |
| Line 3,189: |
Line 3,311: |
| | local args = frame.args or frame:getParent().args or {} | | local args = frame.args or frame:getParent().args or {} |
| | | | |
| − | local qid = args.qid | + | local qid = args.qid or "" |
| − | if qid == "" then qid = nil end | + | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end |
| − | | + | if not qid or not mw.wikibase.entityExists(qid) then return i18n["entity-not-found"] end |
| − | local entity = mw.wikibase.getEntity(qid) | |
| − | if not entity then return i18n["entity-not-found"] end
| |
| | | | |
| − | local labels = entity.labels | + | local labels = mw.wikibase.getEntity(qid).labels |
| | if not labels then return i18n["labels-not-found"] end | | if not labels then return i18n["labels-not-found"] end |
| | | | |
| Line 3,216: |
Line 3,336: |
| | local args = frame.args or frame:getParent().args or {} | | local args = frame.args or frame:getParent().args or {} |
| | | | |
| − | local qid = args.qid | + | local qid = args.qid or "" |
| − | if qid == "" then qid = nil end | + | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end |
| − | | + | if not qid or not mw.wikibase.entityExists(qid) then return i18n["entity-not-found"] end |
| − | local entity = mw.wikibase.getEntity(qid) | |
| − | if not entity then return i18n["entity-not-found"] end
| |
| | | | |
| − | local descriptions = entity.descriptions | + | local descriptions = mw.wikibase.getEntity(qid).descriptions |
| | if not descriptions then return i18n["descriptions-not-found"] end | | if not descriptions then return i18n["descriptions-not-found"] end |
| | | | |
| Line 3,243: |
Line 3,361: |
| | local args = frame.args or frame:getParent().args or {} | | local args = frame.args or frame:getParent().args or {} |
| | | | |
| − | local qid = args.qid | + | local qid = args.qid or "" |
| − | if qid == "" then qid = nil end | + | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end |
| | + | if not qid or not mw.wikibase.entityExists(qid) then return i18n["entity-not-found"] end |
| | | | |
| − | local entity = mw.wikibase.getEntity(qid) | + | local aliases = mw.wikibase.getEntity(qid).aliases |
| − | if not entity then return i18n["entity-not-found"] end
| |
| − | | |
| − | local aliases = entity.aliases
| |
| | if not aliases then return i18n["aliases-not-found"] end | | if not aliases then return i18n["aliases-not-found"] end |
| | | | |
| Line 3,316: |
Line 3,432: |
| | 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] |
| Line 3,326: |
Line 3,442: |
| | end | | end |
| | end | | end |
| | + | |
| | | | |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| Line 3,333: |
Line 3,450: |
| | -- The meanings are given at https://www.mediawiki.org/wiki/Wikibase/DataModel#Dates_and_times | | -- The meanings are given at https://www.mediawiki.org/wiki/Wikibase/DataModel#Dates_and_times |
| | -- 0 = 1 billion years .. 6 = millennium, 7 = century, 8 = decade, 9 = year, 10 = month, 11 = day | | -- 0 = 1 billion years .. 6 = millennium, 7 = century, 8 = decade, 9 = year, 10 = month, 11 = day |
| − | -- Returns nil if it does not exist. | + | -- Returns 0 (or the second unnamed parameter) if the Wikidata does not exist. |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| − | -- Dependencies: parseParam | + | -- Dependencies: parseParam; sourced; |
| | ------------------------------------------------------------------------------- | | ------------------------------------------------------------------------------- |
| | function p.getDatePrecision(frame) | | function p.getDatePrecision(frame) |
| | local args=frame.args | | local args=frame.args |
| | if not args[1] then args=frame:getParent().args end | | if not args[1] then args=frame:getParent().args end |
| | + | local default = tonumber(args[2] or args.default) or 0 |
| | local prop = mw.text.trim(args[1] or "") | | local prop = mw.text.trim(args[1] or "") |
| − | if prop == "" then return nil end | + | if prop == "" then return default end |
| | local qid = args.qid or "" | | local qid = args.qid or "" |
| | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end | | if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end |
| | + | if not qid then return default end |
| | local onlysrc = parseParam(args.onlysourced or args.osd, true) | | local onlysrc = parseParam(args.onlysourced or args.osd, true) |
| | local stat = mw.wikibase.getBestStatements(qid, prop) | | local stat = mw.wikibase.getBestStatements(qid, prop) |
| Line 3,353: |
Line 3,472: |
| | if prec then return prec end | | if prec then return prec end |
| | end | | end |
| | + | return default |
| | end | | end |
| | | | |