Content deleted Content added
No edit summary |
sync from sandbox |
||
Line 11:
local p = {}
local cdate = require("Module:Complex date")._complex_date
-- [[Module:Complex date]] has the following dependencies:
-- Module:i18n/complex date, Module:ISOdate, Module:DateI18n (Module:Date), Module:Formatnum,
-- Module:I18n/date, Module:Yesno, Module:Linguistic, Module:Calendar
-- 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.
-- It would work better if only the authors of the mediawiki page could spell 'millennium'.
local dp = {
[6] = "millennium",
[7] = "century",
[8] = "decade",
[9] = "year",
[10] = "month",
[11] = "day",
}
local i18n =
Line 23 ⟶ 39:
["qualifier-not-found"] = "Qualifier not found.",
["site-not-found"] = "Wikimedia project not found.",
["labels-not-found"] = "No labels found.",
["descriptions-not-found"] = "No descriptions found.",
["aliases-not-found"] = "No aliases found.",
["unknown-datetime-format"] = "Unknown datetime format.",
["local-article-not-found"] = "Article is available on Wikidata, but not on Wikipedia",
Line 29 ⟶ 48:
["months"] =
{
"January", "February", "March", "April", "May", "June
"July", "August", "September", "October", "November", "December"
},
["century"] = "century",
Line 45 ⟶ 64:
["Unknown"] = "Unknown",
["NaN"] = "Not a number",
-- set the following to the name of a tracking category,
-- e.g. "[[Category:Articles with missing Wikidata information]]", or "" to disable:
["missinginfocat"] = "[[Category:Articles with missing Wikidata information]]",
["editonwikidata"] = "Edit this on Wikidata",
["latestdatequalifier"] = function (date) return "before " .. date end,
Line 50 ⟶ 72:
["datenumbersuffix"] = "",
["list separator"] = ", ",
["
[0] = "",
[
[
[
[
}
}
-- This allows a internationisation module to override the above table
Line 80 ⟶ 95:
-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local makeOrdinal = function(cardinal)
local ordsuffix = i18n.ordinal.default
if cardinal % 10 == 1 then
Line 99 ⟶ 116:
-------------------------------------------------------------------------------
-- findLang takes a "langcode" parameter if if supplied and valid
-- otherwise it tries to create it from the user's set language ({{int:lang}})
-- failing that it uses the wiki's content language.
-- It returns a language object
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local findLang = function(langcode)
local langobj
if mw.language.isKnownLanguageTag(langcode) then
langobj = mw.language.new( langcode )
else
langcode = mw.getCurrentFrame():preprocess( '{{int:lang}}' )
if mw.language.isKnownLanguageTag(langcode) then
langobj = mw.language.new( langcode )
else
langobj = mw.language.getContentLanguage()
end
end
return langobj
Line 119 ⟶ 141:
-------------------------------------------------------------------------------
-- roundto takes a
-- and returns it rounded to (sf) significant figures
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local roundto = function(x, sf)
if x == 0 then return 0 end
local s = 1
if x < 0 then
x = -x
s = -1
end
if sf < 1 then sf = 1 end
local
-- if it's integral, cast to an integer:
if
return x
end
Line 139 ⟶ 166:
-- and returns degrees/minutes/seconds according to the precision
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local decimalToDMS = function(x, p)
-- if p is not supplied, use a precision around 0.1 seconds
if not tonumber(p) then p = 1e-4 end
Line 171 ⟶ 200:
-- precision should be between 1 and 1e-6, preferably a power of 10.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local decimalPrecision = function(x, p)
local s = 1
if x < 0 then
x = -x
s = -1
end
-- if p is not supplied, pick an arbitrary precision
if not tonumber(p) then p = 1e-4
end
x =
-- if it's integral, cast to an integer:
if x == math.floor(x) then x = math.floor(x) end
Line 194 ⟶ 230:
-- df = ["dmy" / "mdy" / "y"] default will be "dmy"
-- bc = ["BC" / "BCE"] default will be "BCE"
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local format_Date = function(datetime, dateformat, bc)
Line 214 ⟶ 252:
local dateparts = {}
for word in string.gmatch(dateval, "%w+") do
if word == "BCE" or word == "BC" then -- *** internationalise later ***
postchrist = false
else
Line 221 ⟶ 259:
end
end
if postchrist then bc = "" end -- set AD dates to no suffix *** internationalise later ***
local sep = " " -- separator is nbsp
Line 238 ⟶ 276:
return fdate .. bc
end
-------------------------------------------------------------------------------
-- dateFormat is the handler for properties that are of type "time"
-- It takes timestamp, precision (6 to 11 per mediawiki), dateformat (y/dmy/mdy), BC format (BC/BCE),
-- a plaindate switch (yes/no/adj) to en/disable "sourcing cirumstances"/use adjectival form,
-- any qualifiers for the property, the language, and any adjective to use like 'before'.
-- It passes the date through the "complex date" function
-- and returns a string with the internatonalised date formatted according to preferences.
-------------------------------------------------------------------------------
-- Dependencies: findLang(); cdate(); dp[]
-------------------------------------------------------------------------------
local dateFormat = function(timestamp, dprec, df, bcf, pd, qualifiers, lang, adj)
-- 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")
-- output formatting according to preferences (y/dmy/mdy)
df = (df or ""):lower()
-- just in case date precision is missing
dprec = dprec or 11
-- override more precise dates if required dateformat is year alone:
if df == "y" and dprec > 9 then dprec = 9 end
-- complex date only deals with precisions from 6 to 11, so clip range
dprec = dprec>11 and 11 or dprec
dprec = dprec<6 and 6 or dprec
-- BC format is "BC" or "BCE"
bcf = (bcf or ""):upper()
-- plaindate only needs the first letter (y/n/a)
pd = (pd or ""):sub(1,1)
if pd == "" or pd == "n" or pd == "f" or pd == "0" then pd = false end
-- in case language isn't passed
lang = lang or findLang().code
-- set adj as empty if nil
adj = adj or ""
-- extract the day, month, year from the timestamp
local bc = timestamp:sub(1, 1)=="-" and "BC" or ""
local year, month, day = timestamp:match("[+-](%d*)-(%d*)-(%d*)T")
local iso = tonumber(year) -- if year is missing, let it throw an error
-- this will adjust the date format to be compatible with cdate
-- possible formats are Y, YY, YYY0, YYYY, YYYY-MM, YYYY-MM-DD
if dprec == 6 then iso = math.floor( (iso - 1) / 1000 ) + 1 end
if dprec == 7 then iso = math.floor( (iso - 1) / 100 ) + 1 end
if dprec == 8 then iso = math.floor( iso / 10 ) .. "0" end
if dprec == 10 then iso = year .. "-" .. month end
if dprec == 11 then iso = year .. "-" .. month .. "-" .. day end
-- add "circa" (Q5727902) from "sourcing circumstances" (P1480)
local sc = not pd and qualifiers and qualifiers.P1480
if sc then
for k1, v1 in pairs(sc) do
if v1.datavalue and v1.datavalue.value.id == "Q5727902" then
adj = "circa"
break
end
end
end
local fdate = cdate("", adj, tostring(iso), dp[dprec], bc, "", "", "", "", lang, 1)
-- this may have QuickStatements info appended to it in a div, so remove that
fdate = fdate:gsub(' <div style="display: none;">[^<]*</div>', '')
-- it may also be returned wrapped in a microformat, so remove that
fdate = fdate:gsub("<[^>]*>", "")
-- if 'circa', use the abbreviated form *** internationalise later ***
fdate = fdate:gsub('circa ', '<abbr title="circa">c.</abbr> ')
-- deal with BC/BCE
if bcf == "BCE" then
fdate = fdate:gsub('BC', 'BCE')
end
-- deal with mdy format
if df == "mdy" then
fdate = fdate:gsub("(%d+) (%w+) (%d+)", "%2 %1, %3")
end
-- deal with adjectival form *** internationalise later ***
if pd == "a" then
fdate = fdate:gsub(' century', '-century')
end
return fdate
end
Line 246 ⟶ 362:
-- it makes the empty string and nil into the (boolean) value passed as default
-- allowing the parameter to be true or false by default.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local parseParam = function(param, default)
if param and param ~= "" then
param = param:lower()
if (param == "false") or (param:sub(1,1) == "
return false
else
Line 258 ⟶ 376:
return default
end
end
-------------------------------------------------------------------------------
-- _getSitelink takes the qid of a Wikidata entity passed as |qid=
-- It takes an optional parameter |wiki= to determine which wiki is to be checked for a sitelink
-- If the parameter is blank, then it uses the local wiki.
-- If there is a sitelink to an article available, it returns the plain text link to the article
-- If there is no sitelink, it returns nil.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local _getSitelink = function(qid, wiki)
qid = (qid or ""):upper()
if qid == "" then return nil end
wiki = wiki or ""
local sitelink
if wiki == "" then
sitelink = mw.wikibase.sitelink(qid)
else
sitelink = mw.wikibase.sitelink(qid, wiki)
end
return sitelink
end
-------------------------------------------------------------------------------
-- _getCommonslink takes an optional qid of a Wikidata entity passed as |qid=
-- It returns one of the following in order of preference:
-- the Commons sitelink of the linked Wikidata item;
-- the Commons sitelink of the topic's main category of the linked Wikidata item;
-- the Commons category.
-- If the optional parameter onlycat is true/yes/1 then only categories are returned
-- defaults to false.
-------------------------------------------------------------------------------
-- Dependencies: _getSitelink(); parseParam()
-------------------------------------------------------------------------------
local _getCommonslink = function(qid, onlycat)
qid = (qid or ""):upper()
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return nil end
onlycat = parseParam(onlycat, false)
local sitelink = _getSitelink(qid, "commonswiki")
if onlycat and sitelink and sitelink:sub(1,9) ~= "Category:" then sitelink = nil end
if not sitelink then
-- check for topic's main category
local prop910 = mw.wikibase.getBestStatements(qid, "P910")[1]
if prop910 then
local tmcid = prop910.mainsnak.datavalue.value.id
sitelink = _getSitelink(tmcid, "commonswiki")
end
end
if not sitelink then
-- check for Commons category (string value)
local prop373 = mw.wikibase.getBestStatements(qid, "P373")[1]
if prop373 then
sitelink = prop373.mainsnak.datavalue.value
if sitelink then sitelink = "Category:" .. sitelink end
end
end
return sitelink
end
Line 268 ⟶ 447:
-- a second (boolean) value is also returned, value is true when the label exists
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local labelOrId = function(id)
local label = mw.wikibase.label(id)
if label then
Line 275 ⟶ 456:
return id, false
end
end
-------------------------------------------------------------------------------
-- linkedItem takes an entity-id and returns a string, linked if possible.
-- This is the handler for "wikibase-item". Preferences:
-- 1. Display linked disambiguated sitelink if it exists
-- 2. Display linked label if it is a redirect
-- 3. TBA: Display an inter-language link for the label if it exists other than in default language
-- 4. Display unlinked label if it exists
-- 5. Display entity-id for now to indicate a label could be provided
-------------------------------------------------------------------------------
-- Dependencies: labelOrId()
-------------------------------------------------------------------------------
local linkedItem = function(id, lprefix, lpostfix, prefix, postfix)
lprefix = lprefix or "" -- toughen against nil values passed
lpostfix = lpostfix or ""
prefix = prefix or ""
postfix = postfix or ""
local disp
local sitelink = mw.wikibase.sitelink(id)
local label, islabel = labelOrId(id)
if mw.site.siteName ~= "Wikimedia Commons" then
if sitelink then
-- strip any namespace or dab from the sitelink and use that as label
local pos = sitelink:find(":") or 0
label = sitelink:sub(pos+1):gsub("%s%(.+%)$", ""):gsub(",.+$", "")
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
elseif islabel then
-- no sitelink, label exists, so check if a redirect with that title exists
local artitle = mw.title.new(label, 0)
if artitle and artitle.redirectTarget then
-- there's a redirect with the same title as the label, so let's link to that
disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
else
-- no sitelink, label exists, not a redirect, so output the plain label
disp = prefix .. label .. postfix
end -- test if article title exists as redirect on current Wiki
else
-- no sitelink and no label, so return whatever was returned from labelOrId for now
-- add tracking category [[Category:Articles with missing Wikidata information]]
disp = prefix .. label .. postfix .. i18n.missinginfocat
end
else
local ccat = mw.wikibase.getBestStatements(id, "P373")[1]
if ccat then
ccat = ccat.mainsnak.datavalue.value
disp = "[[" .. lprefix .. "Category:" .. ccat .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
elseif sitelink then
-- this asumes that if a sitelink exists, then a label also exists
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
else
-- no sitelink and no Commons cat, so return label from labelOrId for now
disp = prefix .. label .. postfix
end
end
return disp
end
Line 282 ⟶ 520:
-- it counts how many references are sourced to something not containing the word "wikipedia"
-- it returns a boolean = true if there are any sourced references.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local sourced = function(claim)
Line 304 ⟶ 544:
-- "best" will override the other flags, and set p and n
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local setRanks = function(rank)
rank = (rank or ""):lower()
-- if nothing passed, return preferred and normal
Line 330 ⟶ 572:
-- and (2) a table containing all of the statements for the propertyID and relevant Qid
-- if "best" ranks are requested, it returns those instead of all non-deprecated ranks
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
local parseInput = function(frame, input_parm, property_id)
Line 343 ⟶ 587:
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
-- if there's no Wikidata item for the current page return nil
if not qid then return false,
-- The blacklist is passed in named parameter |suppressfields
Line 368 ⟶ 612:
-- Otherwise see if this field is on the whitelist:
-- needs a bit more logic because find will return its second value = 0 if fieldname
-- but nil if fieldname not found on whitelist
local _, found = whitelist:find(fieldname)
Line 388 ⟶ 632:
-- no property on Wikidata
return false, nil
end
-------------------------------------------------------------------------------
-- createicon assembles the "Edit at Wikidata" pen icon.
-- It returns a wikitext string.
-------------------------------------------------------------------------------
-- Dependencies: i18n[];
-------------------------------------------------------------------------------
local createicon = function(langcode, entityID, propertyID)
local icon = " [[" .. i18n["filespace"]
icon = icon .. ":Blue pencil.svg |frameless |text-top |10px |alt="
icon = icon .. i18n["editonwikidata"]
icon = icon .. "|link=https://www.wikidata.org/wiki/" .. entityID
icon = icon .. "?uselang=" .. langcode
icon = icon .. "#" .. propertyID .. "|" .. i18n["editonwikidata"] .. "]]"
return icon
end
Line 393 ⟶ 654:
-------------------------------------------------------------------------------
-- assembleoutput takes the sequence table containing the property values
-- and formats it according to switches given. It returns a string or nil.
--
-------------------------------------------------------------------------------
-- Dependencies: parseParam();
-------------------------------------------------------------------------------
local
-- sorted is a boolean passed to enable sorting of the values returned
Line 440 ⟶ 701:
-- if a pen icon is wanted add it the end of the last value
if not noic then
out[#out] = out[#out] .. createicon(args.langobj.code, entityID, propertyID)
end
if list == "" then
Line 462 ⟶ 717:
end
return strout
end
-------------------------------------------------------------------------------
-- rendersnak takes a table (propval) containing the information stored on one property value
-- and returns the value as a string and its language if monolingual text.
-- It handles data of type:
-- wikibase-item
-- time
-- string, url, commonsMedia, external-id
-- quantity
-- globe-coordinate
-- monolingualtext
-- It also requires linked, the link/pre/postfixes, uabbr, and the arguments passed from frame.
-- The optional filter parameter allows quantities to be be filtered by unit.
-------------------------------------------------------------------------------
-- Dependencies: parseParam(); labelOrId(); i18n[]; dateFormat();
-- roundto(); decimalPrecision(); decimalToDMS();
-------------------------------------------------------------------------------
local rendersnak = function(propval, args, linked, lpre, lpost, pre, post, uabbr, filter)
lpre = lpre or ""
lpost = lpost or ""
pre = pre or ""
post = post or ""
local snak = propval.mainsnak or propval
local dv = snak.datavalue
local dtype = propval.datatype or propval.mainsnak.datatype
dv = dv and dv.value
-- value and monolingual text language code returned
local val, mlt
if propval.rank and not args.reqranks[propval.rank:sub(1, 1)] then
-- val is nil: value has a rank that isn't requested
------------------------------------
elseif snak.snaktype == "somevalue" then -- value is unknown
val = i18n["Unknown"]
------------------------------------
elseif snak.snaktype == "novalue" then -- value is none
-- val = "No value" -- don't return anything
------------------------------------
elseif dtype == "wikibase-item" then -- data type is a wikibase item:
-- it's wiki-linked value, so output as link if enabled and possible
local qnumber = dv.id
if linked then
val = linkedItem(qnumber, lpre, lpost, pre, post)
else -- no link wanted so test for lang code
local label, islabel = labelOrId(qnumber)
local langlabel = mw.wikibase.getLabelByLang(qnumber, args.lang)
if langlabel then
label = mw.text.nowiki( langlabel )
end
val = pre .. label .. post
end -- test for link required
------------------------------------
elseif dtype == "time" then -- data type is time:
-- time is in timestamp format
-- date precision is integer per mediawiki
-- output formatting according to preferences (y/dmy/mdy)
-- BC format as BC or BCE
-- plaindate is passed to disable looking for "sourcing cirumstances"
-- or to set the adjectival form
-- qualifiers (if any) is a nested table or nil
-- lang is given, or user language, or site language
val = dateFormat(dv.time, dv.precision, args.df, args.bc, pd, propval.qualifiers, args.lang)
------------------------------------
-- data types which are strings:
elseif dtype == "commonsMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then
-- commonsMedia or external-id or string or url
-- all have mainsnak.datavalue.value as string
if (lpre == "" or lpre == ":") and lpost == "" then
-- don't link if no linkpre/postfix or linkprefix is just ":"
val = pre .. dv .. post
else
val = "[[" .. lpre .. dv .. lpost .. "|" .. pre .. dv .. post .. "]]"
end -- check for link requested (i.e. either linkprefix or linkpostfix exists)
------------------------------------
-- data types which are quantities:
elseif dtype == "quantity" then
-- quantities have mainsnak.datavalue.value.amount and mainsnak.datavalue.value.unit
-- the unit is of the form http://www.wikidata.org/entity/Q829073
--
-- implement a switch to turn on/off numerical formatting later
local fnum = true
--
-- a switch to turn on/off conversions - only for en-wiki
local conv = parseParam(args.conv or args.convert, false)
-- if we have conversions, we won't have formatted numbers or scales
if conv then
fnum = false
args.scale = "0"
end
--
-- convert amount to a number
local amount = tonumber(dv.amount) or i18n["NaN"]
--
-- scale factor for millions, billions, etc.
local sc = tostring(args.scale or ""):sub(1,1):lower()
local scale
if sc == "a" then
-- automatic scaling
if amount > 1e15 then
scale = 12
elseif amount > 1e12 then
scale = 9
elseif amount > 1e9 then
scale = 6
elseif amount > 1e6 then
scale = 3
else
scale = 0
end
else
scale = tonumber(args.scale) or 0
if scale < 0 or scale > 12 then scale = 0 end
scale = math.floor(scale/3) * 3
end
local factor = 10^scale
amount = amount / factor
-- ranges:
local range = ""
-- check if upper and/or lower bounds are given and significant
local upb = tonumber(dv.upperBound)
local lowb = tonumber(dv.lowerBound)
if upb and lowb then
-- differences rounded to 2 sig fig:
local posdif = roundto(upb - amount, 2) / factor
local negdif = roundto(amount - lowb, 2) / factor
upb, lowb = amount + posdif, amount - negdif
-- round scaled numbers to integers or 4 sig fig
if (scale > 0 or sc == "a") then
if amount < 1e4 then
amount = roundto(amount, 4)
else
amount = math.floor(amount + 0.5)
end
end
if fnum then amount = args.langobj:formatNum( amount ) end
if posdif ~= negdif then
-- non-symmetrical
range = " +" .. posdif .. " -" .. negdif
elseif posdif ~= 0 then
-- symmetrical and non-zero
range = " ±" .. posdif
else
-- otherwise range is zero, so leave it as ""
end
else
-- round scaled numbers to integers or 4 sig fig
if (scale > 0 or sc == "a") then
if amount < 1e4 then
amount = roundto(amount, 4)
else
amount = math.floor(amount + 0.5)
end
end
if fnum then amount = args.langobj:formatNum( amount ) end
end
-- unit names and symbols:
-- extract the qid in the form 'Qnnn' from the value.unit url
-- and then fetch the label from that - or symbol if unitabbr is true
local unit = ""
local usep = ""
local usym = ""
local unitqid = string.match( dv.unit, "(Q%d+)" )
if filter and unitqid ~= filter then return nil end
if unitqid then
local uname = mw.wikibase.getLabelByLang(unitqid, args.lang) or ""
if uname ~= "" then usep, unit = " ", uname end
if uabbr then
-- see if there's a unit symbol (P5061)
local unitsymbols = mw.wikibase.getAllStatements(unitqid, "P5061")
-- construct fallback table
local fbtbl = mw.language.getFallbacksFor( args.lang )
table.insert( fbtbl, 1, args.lang )
found = false
for idx1, us in ipairs(unitsymbols) do
for idx2, fblang in ipairs(fbtbl) do
if us.mainsnak.datavalue.value.language == fblang then
usym = us.mainsnak.datavalue.value.text
found = true
break
end
if found then break end
end -- loop through fallback table
end -- loop through values of P5061
if found then usep, unit = " ", usym end
end
end
-- format display:
if conv and usym ~= "" then
if range == "" then
val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {amount, usym}}
else
val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {lowb, "to", upb, usym}}
end
elseif unit == "$" or unit == "£" then
val = unit .. amount .. range .. i18n.multipliers[scale]
else
val = amount .. range .. i18n.multipliers[scale] .. usep .. unit
end
------------------------------------
-- datatypes which are global coordinates:
elseif dtype == "globe-coordinate" then
-- 'display' parameter defaults to "inline, title" *** unused for now ***
-- local disp = args.display or ""
-- if disp == "" then disp = "inline, title" end
--
-- format parameter switches from deg/min/sec to decimal degrees
-- default is deg/min/sec -- decimal degrees needs |format = dec
local form = (args.format or ""):lower():sub(1,3)
if form ~= "dec" then form = "dms" end
--
-- show parameter allows just the latitude or longitude to be shown
local show = (args.show or ""):lower()
if show ~= "longlat" then show = show:sub(1,3) end
--
local lat, long, prec = dv.latitude, dv.longitude, dv.precision
if show == "lat" then
val = decimalPrecision(lat, prec)
elseif show == "lon" then
val = decimalPrecision(long, prec)
elseif show == "longlat" then
val = decimalPrecision(long, prec) .. ", " .. decimalPrecision(lat, prec)
else
local ns = "N"
local ew = "E"
if lat < 0 then
ns = "S"
lat = - lat
end
if long < 0 then
ew = "W"
long = - long
end
if form == "dec" then
lat = decimalPrecision(lat, prec)
long = decimalPrecision(long, prec)
val = lat .. "°" .. ns .. " " .. long .. "°" .. ew
else
local latdeg, latmin, latsec = decimalToDMS(lat, prec)
local longdeg, longmin, longsec = decimalToDMS(long, prec)
if latsec == 0 and longsec == 0 then
if latmin == 0 and longmin == 0 then
val = latdeg .. "°" .. ns .. " " .. longdeg .. "°" .. ew
else
val = latdeg .. "°" .. latmin .. "′" .. ns .. " "
val = val .. longdeg .. "°".. longmin .. "′" .. ew
end
else
val = latdeg .. "°" .. latmin .. "′" .. latsec .. "″" .. ns .. " "
val = val .. longdeg .. "°" .. longmin .. "′" .. longsec .. "″" .. ew
end
end
end
------------------------------------
elseif dtype == "monolingualtext" then -- data type is Monolingual text:
-- has mainsnak.datavalue.value as a table containing language/text pairs
-- collect all the values in 'out' and languages in 'mlt' and process them later
val = pre .. dv.text .. post
mlt = dv.language
------------------------------------
else
-- some other data type so write a specific handler
val = "unknown data type: " .. dtype
end -- of datatype/unknown value/sourced check
return val, mlt
end
Line 471 ⟶ 992:
-- and qualifiers that match the qualifierID if supplied.
-------------------------------------------------------------------------------
-- Dependencies: parseParam(); sourced(); labelOrId(); i18n.latestdatequalifier(); format_Date();
-- makeOrdinal(); roundto(); decimalPrecision(); decimalToDMS(); assembleoutput();
-------------------------------------------------------------------------------
local function propertyvalueandquals(objproperty, args, qualID)
-- needs this style of declaration because it's re-entrant
-- onlysourced is a boolean passed to return only values sourced to other than Wikipedia
Line 500 ⟶ 1,022:
-- useful when when multiple values are returned and indirect links are needed
-- any double-quotes " are stripped out, so that spaces may be passed
local lprefix = (args.linkprefix or args.lp or ""):gsub('"', '')
-- linkpostfix is a string that may be nil, empty (""), or a string of characters
Line 514 ⟶ 1,036:
-- unitabbr is a boolean passed to enable unit abbreviations for common units
-- if nothing or an empty string is passed set it false
local uabbr = parseParam(args.unitabbr or args.uabbr, false)
-- qualsonly is a boolean passed to return just the qualifiers
-- if nothing or an empty string is passed set it false
local qualsonly = parseParam(args.qualsonly or args.qo, false)
-- maxvals is a string that may be nil, empty (""), or a number
Line 521 ⟶ 1,047:
local maxvals = tonumber(args.maxvals) or 0
-- pd (plain date) is a string: yes/true/1 | no/false/0 | adj
-- to disable/enable "sourcing cirumstances" or use adjectival form for the plain date
local pd = args.plaindate or args.pd or "no"
local lang = args.lang
-- all proper values of a Wikidata property will be the same type as the first
-- qualifiers don't have a mainsnak, properties do
local datatype = objproperty[1].datatype or objproperty[1].mainsnak.datatype
-- out holds the values for this property
--
local out = {}
local
for k, v in pairs(objproperty) do
if (onlysrc and not sourced(v)) or (qualsonly and qualID) then
-- no value: it isn't sourced when onlysourced=true
-- or only qualifiers are requested
else
out[#out+1], mlt[#out+1] = rendersnak(v, args, linked, lprefix, lpostfix, prefix, postfix, uabbr)
end
-- See if qualifiers are to be returned:
local snak = v.mainsnak or v
if v.qualifiers and qualID and snak.snaktype=="value" then
local qsep = (args.qsep or ""):gsub('"', '')
Line 796 ⟶ 1,076:
["prefix"] = args.qprefix,
["postfix"] = args.qpostfix,
["linkprefix"] = args.qlinkprefix or args.qlp,
["linkpostfix"] = args.qlinkpostfix,
["wdl"] = "false",
Line 803 ⟶ 1,083:
["sorted"] = args.qsorted,
["noicon"] = "true",
["list"] =
["sep"] = qsep,
["langobj"] = args.langobj,
["lang"] = args.langobj.code,
}
local qlist = {}
local t1, t2
-- see if we want all qualifiers
if
-- the values in the order table are the keys for the qualifiers table:
for k1, v1 in ipairs(v["qualifiers-order"]) do
if v1 == "P1326" then
local ts = v.qualifiers[v1][1].datavalue.value.time
local dp = v.qualifiers[v1][1].datavalue.value.precision
qlist[#qlist + 1] = dateFormat(ts, dp, args.df, args.bc, pd, "", lang, "before")
else
qlist[#qlist + 1] = assembleoutput(propertyvalueandquals(v.qualifiers[v1], qargs), qargs)
end
end
else
local ql = propertyvalueandquals(v1, qargs)
for k1, v1 in ipairs(ql) do
if k1 == "P1326" then
local ts = v1[1].datavalue.value.time
local dp = v1[1].datavalue.value.precision
qlist[#qlist + 1] = dateFormat(ts, dp, args.df, args.bc, pd, "", lang, "before")
else
qlist[#qlist + 1] = v1
end
end
end
-- see if we want date/range
elseif qualID == "DATES" then
qargs.maxvals = 1
for k1, v1 in pairs(v.qualifiers) do
if k1 == "P580" then -- P580 is "start time"
t1 = propertyvalueandquals(v1, qargs)[1] or ""
elseif k1 == "P582" then -- P582 is "end time"
t2 = propertyvalueandquals(v1, qargs)[1] or ""
end
end
else
for q in mw.text.gsplit(qualID, "%p") do -- split at punctuation and iterate
q = mw.text.trim(q):upper() -- remove whitespace and capitalise
if q == "P1326" then
-- latest date, so supply 'before' as well. Assume one date value.
for k1, v1 in pairs(v.qualifiers) do
if k1 == "P1326" then
local ts = v1[1].datavalue.value.time
local dp = v1[1].datavalue.value.precision
qlist[#qlist + 1] = dateFormat(ts, dp, args.df, args.bc, pd, "", lang, "before")
end
end
else
for k1, v1 in pairs(v.qualifiers) do
if k1 == q then
local ql = propertyvalueandquals(v1, qargs)
for k2, v2 in ipairs(ql) do
qlist[#qlist + 1] = v2
end
end
end
end
end -- of loop through list of qualifiers in qualID
end -- of testing for what qualID is
local t = t1 .. t2
-- *** internationalise date separators later ***
Line 834 ⟶ 1,155:
if #qlist > 0 then
local qstr = assembleoutput(qlist, qargs)
if qualsonly then
out[#out+1] = qstr
else
out[#out] = out[#out] .. " (" .. qstr .. ")"
end
elseif t > "" then
-- *** internationalise date separators later ***
local dsep = "–"
if t:find("%s") or t:find(" ") then dsep = " – " end
if qualsonly then
out[#out+1] = t1 .. dsep .. t2
else
out[#out] = out[#out] .. " (" .. t1 .. dsep .. t2 .. ")"
end
end
end -- of test for qualifiers wanted
if maxvals > 0 and #out >= maxvals then break end
end -- of for each value loop
Line 853 ⟶ 1,186:
found = false
for idx1, lang1 in ipairs(fbtbl) do
for idx2, lang2 in ipairs(
if (lang1 == lang2) and not found then
bestval = out[idx2]
Line 872 ⟶ 1,205:
return out
end
-------------------------------------------------------------------------------
-- Common code for p.getValueByQual and p.getValueByLang
-------------------------------------------------------------------------------
-- Dependencies: parseParam; setRanks; parseInput; sourced; assembleoutput;
-------------------------------------------------------------------------------
local _getvaluebyqual = function(frame, qualID, checkvalue)
-- The property ID that will have a qualifier is the first unnamed parameter
local propertyID = mw.text.trim(frame.args[1] or "")
if propertyID == "" then return "no property supplied" end
if qualID == "" then return "no qualifier supplied" end
-- onlysourced is a boolean passed to return property values
-- only when property values are sourced to something other than Wikipedia
-- if nothing or an empty string is passed set it true
-- if "false" or "no" or 0 is passed set it false
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)
-- set the requested ranks flags
frame.args.reqranks = setRanks(frame.args.rank)
-- set a language object and code in the frame.args table
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
-- check for locally supplied parameter in second unnamed parameter
-- success means no local parameter and the property exists
local qid, props = parseInput(frame, frame.args[2], propertyID)
if qid then
local out = {}
-- Scan through the values of the property
-- we want something like property is "pronunciation audio (P443)" in propertyID
-- with a qualifier like "language of work or name (P407)" in qualID
-- whose value has the required ID, like "British English (Q7979)", in qval
for k1, v1 in pairs(props) do
if v1.mainsnak.snaktype == "value" and v1.mainsnak.datavalue.type == "string" then
-- We'll only deal with returning strings for now
-- so check if it has the right qualifier
local v1q = v1.qualifiers
if v1q and v1q[qualID] then
if onlysrc == false or sourced(v1) then
-- if we've got this far, we have a (sourced) claim with qualifiers
-- so see if matches the required value
-- We'll only deal with wikibase-items for now
if v1q[qualID][1].datatype == "wikibase-item" then
if checkvalue(v1q[qualID][1].datavalue.value.id) then
out[#out + 1] = v1.mainsnak.datavalue.value
end
end
end -- of check for sourced
end -- of check for matching required value and has qualifiers
else
return "not string"
end -- of check for string
end -- of loop through values of propertyID
return assembleoutput(out, frame.args, qid, propertyID)
else
return props -- either local parameter or nothing
end -- of test for success
return nil
end
-------------------------------------------------------------------------------
-- _location takes Q-id and follows P131 (located in the administrative territorial entity)
-- or P276 (___location) or P706 (located on terrain feature)
-- from the initial item to higher level territories/locations until it reaches the highest.
-- An optional boolean, 'first', determines whether the first item is returned (default: false).
-- An optional boolean 'skip' toggles the display to skip to the last item (default: false).
-- It returns a table containing the locations - linked where possible, except for the highest.
-------------------------------------------------------------------------------
-- Dependencies: findLang(); labelOrId(); linkedItem
-------------------------------------------------------------------------------
local _location = function(qid, first, skip)
first = parseParam(first, false)
skip = parseParam(skip, false)
local out = {}
local langcode = findLang():getCode()
local finished = false
local count = 0
repeat
local prop = mw.wikibase.getBestStatements(qid, "P131")[1] or mw.wikibase.getBestStatements(qid, "P276")[1] or mw.wikibase.getBestStatements(qid, "P706")[1]
-- check if it's an instance of (P31) a country (Q6256) and terminate the chain if it is
local inst = mw.wikibase.getAllStatements(qid, "P31")
if #inst > 0 then
for k, v in ipairs(inst) do
local instid = v.mainsnak.datavalue.value.id
-- 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
prop = nil -- this will ensure this is treated as top-level ___location
break
end
end
end
if prop and prop.mainsnak.datavalue then
if not skip or count == 0 then
out[#out+1] = linkedItem(qid, ":", "", "", "") -- get a linked value if we can
end
qid = prop.mainsnak.datavalue.value.id
else
-- This is top-level ___location, so get short name except when this is the first item
-- Use full label if there's no short name or this is the first item
props = mw.wikibase.getAllStatements(qid, "P1813")
-- if there's a short name and this isn't the only item
if props[1] and (#out > 0)then
local shortname
-- short name is monolingual text, so look for match to the local language
-- choose the shortest 'short name' in that language
for k, v in pairs(props) do
if v.mainsnak.datavalue.value.language == langcode then
local name = v.mainsnak.datavalue.value.text
if (not shortname) or (#name < #shortname) then
shortname = name
end
end
end
-- add the shortname if one is found, fallback to the label
-- but skip it if it's "USA"
if shortname ~= "USA" then
out[#out+1] = shortname or labelOrId(qid)
else
if skip then out[#out+1] = "US" end
end
else
-- no shortname, so just add the label
local loc = labelOrId(qid)
-- exceptions go here:
if loc == "United States of America" then
out[#out+1] = "United States"
else
out[#out+1] = loc
end
end
finished = true
end
count = count + 1
until finished or count >= 10 -- limit to 10 levels to avoid infinite loops
if not first then table.remove(out, 1) end
return out
end
-------------------------------------------------------------------------------
Line 890 ⟶ 1,368:
frame.args = frame:getParent().args
if not frame.args[1] then return i18n.errors["No property supplied"] end
end
-- parameter sets for commonly used groups of parameters
local paraset = tonumber(frame.args.ps or frame.args.parameterset or 0)
if paraset == 1 then
frame.args.rank = "best"
frame.args.fetchwikidata = "ALL"
frame.args.onlysourced = "no"
frame.args.noicon = "true"
elseif paraset == 2 then
-- second set goes here
end
Line 908 ⟶ 1,397:
if qualID == "" then qualID = nil end
-- set a language object and code in the frame.args table
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
-- table 'out' stores the return value(s):
Line 933 ⟶ 1,423:
return p.getValue(frame)
end
-------------------------------------------------------------------------------
Line 939 ⟶ 1,430:
-- optional 'display' parameter is allowed, defaults to "inline, title"
-------------------------------------------------------------------------------
-- Dependencies: setRanks(); parseInput(); decimalPrecision();
-------------------------------------------------------------------------------
p.getCoords = function(frame)
Line 989 ⟶ 1,480:
-- when the property is unsourced (or only sourced to Wikipedia)
-------------------------------------------------------------------------------
-- Dependencies: parseParam(); setRanks(); parseInput(); sourced();
-- propertyvalueandquals(); assembleoutput -- labelOrId(); i18n.latestdatequalifier(); format_Date();
-- findLang(); makeOrdinal(); roundto(); decimalPrecision(); decimalToDMS(); -------------------------------------------------------------------------------
p.getQualifierValue = function(frame)
Line 1,036 ⟶ 1,529:
local quals = v1.qualifiers[qualifierID]
if quals then
-- can't reference qualifer, so set onlysourced = "no" (not boolean)
local qargs = frame.args
qargs.onlysourced = "no"
local vals = propertyvalueandquals(quals, qargs, qid)
for k, v in pairs(vals) do
out[#out + 1] = v
Line 1,051 ⟶ 1,547:
return nil
end
-------------------------------------------------------------------------------
-- getValueByQual gets the value of a property which has a qualifier with a given entity value
Line 1,072 ⟶ 1,570:
return _getvaluebyqual(frame, qualID, checkQID)
end
-------------------------------------------------------------------------------
-- getValueByLang gets the value of a property which has a qualifier P407
Line 1,084 ⟶ 1,584:
-------------------------------------------------------------------------------
p.getValueByLang = function(frame)
-- The language code for the qualifier we want to match is in named parameter |lang=
local langcode = frame.args.lang or ""
Line 1,101 ⟶ 1,601:
return _getvaluebyqual(frame, "P407", checkLanguage)
end
-------------------------------------------------------------------------------
-- getValueByRefSource gets the value of a property which has a reference "stated in" (P248)
-- whose value has the given entity code.
-- The call needs:
-- a property ID (the unnamed parameter or 1=Pxxx)
-- the entity ID of a value to match where the reference is stated in (match=Qzzz)
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented
-------------------------------------------------------------------------------
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput;
-------------------------------------------------------------------------------
p.getValueByRefSource = function(frame)
-- The property ID that we want to check is the first unnamed parameter
local propertyID = mw.text.trim(frame.args[1] or ""):upper()
if propertyID == "" then return "no property supplied" end
-- The Q-id of the value we want to match is in named parameter |qvalue=
local qval = (frame.args.match or ""):upper()
if qval == "" then qval = "Q21540096" end
local unit = (frame.args.unit or ""):upper()
if unit == "" then unit = "Q4917" end
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)
Line 1,123 ⟶ 1,630:
frame.args.reqranks = setRanks(frame.args.rank)
-- set a language object and code in the frame.args table
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
local linked = parseParam(frame.args.linked, true)
local uabbr = parseParam(frame.args.uabbr or frame.args.unitabbr, false)
-- qid not nil means no local parameter and the property exists
local qid, props = parseInput(frame, frame.args[2], propertyID)
if qid then
local out = {}
local mlt= {}
for k1, v1 in pairs(props) do
if
if v1.references then
for k2, v2 in pairs(v1.references) do
if v2.snaks.P248 then
for k3, v3 in pairs(v2.snaks.P248) do
if
out[#out+1], mlt[#out+1] = rendersnak(v1, frame.args, linked, "", "", "", "", uabbr, unit)
--
break
end
end -- of test for match
end -- of loop through values "stated in"
end -- of
end -- of
end -- of test that references exist
end -- of test for sourced
end -- of loop through values of propertyID
if #mlt > 0 then
local langcode = frame.args.lang
langcode = mw.text.split( langcode, '-', true )[1]
local fbtbl = mw.language.getFallbacksFor( langcode )
table.insert( fbtbl, 1, langcode )
bestval = ""
found = false
for idx1, lang1 in ipairs(fbtbl) do
for idx2, lang2 in ipairs(mlt) do
if (lang1 == lang2) and not found then
bestval = out[idx2]
found = true
break
end
end -- loop through values of property
end -- loop through fallback languages
if found then
-- replace output table with a table containing the best value
out = { bestval }
else
-- more than one value and none of them on the list of fallback languages
-- sod it, just give them the first one
out = { out[1] }
end
end
return assembleoutput(out, frame.args, qid, propertyID)
else
return props --
end -- of test for success
end
-------------------------------------------------------------------------------
-- getCommonsLink takes an optional qid of a Wikidata entity passed as |qid=
-- It returns one of the following in order of preference:
-- the Commons sitelink of the linked Wikidata item;
-- the Commons sitelink of the topic's main category of the linked Wikidata item;
-------------------------------------------------------------------------------
-- Dependencies: _getCommonslink(); _getSitelink()
-------------------------------------------------------------------------------
p.getCommonsLink = function(frame)
return _getCommonslink(frame.args.qid, frame.args.onlycat or frame.args.onlycategories)
end
-------------------------------------------------------------------------------
-- getSitelink takes the qid of a Wikidata entity passed as |qid=
-- It takes an optional parameter |wiki= to determine which wiki is to be checked for a sitelink
-- If the parameter is blank, then it uses the local wiki.
-- If there is a sitelink to an article available, it returns the plain text link to the article
-- If there is no sitelink, it returns nil.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getSiteLink = function(frame)
return _getSitelink(frame.args.qid, frame.args.wiki or mw.text.trim(frame.args[1] or ""))
end
-------------------------------------------------------------------------------
Line 1,167 ⟶ 1,729:
-- If there is no sitelink, it returns the label as plain text.
-- If there is no label in the local language, it displays the qid instead.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getLink = function(frame)
Line 1,174 ⟶ 1,738:
local label = labelOrId(itemID)
if sitelink then
return "[[:" .. sitelink .. "|" .. label .. "]]"
else
return label
Line 1,185 ⟶ 1,749:
-- It returns the Wikidata label for the local language as plain text.
-- If there is no label in the local language, it displays the qid instead.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getLabel = function(frame)
Line 1,198 ⟶ 1,764:
-- If there is a sitelink to an article on the local Wiki, it returns the sitelink as plain text.
-- If there is no sitelink, it returns nothing.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getAT = function(frame)
Line 1,213 ⟶ 1,781:
-- It returns the article description for the Wikidata entity if the local parameter is "Wikidata".
-- Nothing is returned if the description doesn't exist or "none" is passed as the local parameter.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getDescription = function(frame)
Line 1,232 ⟶ 1,802:
-- returns nothing if the page is not connected to Wikidata
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.pageId = function(frame)
return mw.wikibase.getEntityIdForCurrentPage()
end
Line 1,240 ⟶ 1,812:
-- formatDate is a wrapper to export the private function format_Date
-------------------------------------------------------------------------------
-- Dependencies: format_Date();
-------------------------------------------------------------------------------
p.formatDate = function(frame)
Line 1,248 ⟶ 1,820:
-------------------------------------------------------------------------------
-- ___location is a wrapper to export the private function _location
-- it takes the entity-id as qid or the first unnamed parameter
-- optional boolean parameter first toggles the display of the first item
-- optional boolean parameter skip toggles the display to skip to the last item
-------------------------------------------------------------------------------
-- Dependencies: _location();
-------------------------------------------------------------------------------
p.___location = function(frame)
local qid = mw.text.trim(frame.args.qid or frame.args[1] or ""):upper()
if qid == "" then return "No id supplied" end
local first = mw.text.trim(frame.args.first or "")
local skip = mw.text.trim(frame.args.skip or "")
return table.concat( _location(qid, first, skip), ", " )
end
-------------------------------------------------------------------------------
-- checkBlacklist implements a test to check whether a named field is allowed
-- returns true if the field is not blacklisted (i.e. allowed)
-- returns false if the field is blacklisted (i.e. disallowed)
Line 1,255 ⟶ 1,844:
-- {{#if:{{#invoke:WikidataIB |checkBlacklist |name=Jim |suppressfields=Dave; Joe; Fred}} | not blacklisted | blacklisted}}
-- displays "not blacklisted"
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.checkBlacklist = function(frame)
Line 1,282 ⟶ 1,873:
-- with a form that uses just a single call to Wikidata:
-- {{#invoke |WikidataIB |emptyor |1= <span class="xxx">{{#invoke:WikidataIB |getvalue |P99 |fwd=ALL}}</span> }}
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.emptyor = function(frame)
Line 1,311 ⟶ 1,904:
-- getLang returns the MediaWiki language code of the current content.
-- If optional parameter |style=full, it returns the language name.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getLang = function(frame)
local style = (frame.args.style or ""):lower()
Line 1,318 ⟶ 1,914:
end
return langcode
end
-------------------------------------------------------------------------------
-- findLanguage exports the local findLang() function
-- It takes an optional language code and returns, in order of preference:
-- the code if a known language;
-- the user's language, if set;
-- the server's content language.
-------------------------------------------------------------------------------
-- Dependencies: findLang
-------------------------------------------------------------------------------
p.findLanguage = function(frame)
return findLang(frame.args.lang or frame.args[1]).code
end
Line 1,326 ⟶ 1,936:
-- failing that, the Wikidata entity ID asociated with the curent page, if it exists
-- otherwise, nothing
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getQid = function(frame)
local qid = (frame.args.qid or ""):upper()
Line 1,331 ⟶ 1,944:
if qid ~= "" then return qid end
-- check if there's a "category's main topic (P301)":
if qid then
local prop301 = mw.wikibase.getBestStatements(qid, "P301")
Line 1,341 ⟶ 1,954:
-- otherwise return the page qid (if any)
return qid
end
-------------------------------------------------------------------------------
-- followQid takes two optional parameters: qid and props
-- If qid is not given, it uses the qid for the connected page
-- or returns nil if there isn't one.
-- props is a list of properties, separated by punctuation.
-- 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,
-- and the search terminates.
-- If props is not given, the qid is returned.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.followQid = function(frame)
local qid = (frame.args.qid or ""):upper()
if qid == "" then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
if not qid then return nil end
local props = (frame.args.props or ""):upper()
if props ~= "" then
for p in mw.text.gsplit(props, "%p") do -- split at punctuation and iterate
p = mw.text.trim(p)
for i, v in ipairs( mw.wikibase.getBestStatements(qid, p) ) do
local linkedid = v.mainsnak.datavalue and v.mainsnak.datavalue.value.id
if linkedid then
return linkedid
end
end -- loop through values of property to follow
end -- loop through list of properties to follow
end
return qid
end
-------------------------------------------------------------------------------
-- siteID returns the root of the globalSiteID
-- e.g. "en" for "enwiki", "enwikisource", etc.
-- treats "en-gb" as "en", etc.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.siteID = function(frame)
local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
-- This deals with specific exceptions: be-tarask -> be-x-old
if txtlang == "be-tarask" then
return "be_x_old"
end
local pos = txtlang:find("-")
local ret = ""
if pos then
ret = txtlang:sub(1, pos-1)
else
ret = txtlang
end
return ret
end
-------------------------------------------------------------------------------
-- projID returns the code used to link to the reader's language's project
-- e.g "en" for [[:en:WikidataIB]]
-- treats "en-gb" as "en", etc.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.projID = function(frame)
local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
-- This deals with specific exceptions: be-tarask -> be-x-old
if txtlang == "be-tarask" then
return "be-x-old"
end
local pos = txtlang:find("-")
local ret = ""
if pos then
ret = txtlang:sub(1, pos-1)
else
ret = txtlang
end
return ret
end
Line 1,349 ⟶ 2,046:
-- The number is the first unnamed parameter or "|num="
-------------------------------------------------------------------------------
-- Dependencies: findLang()
-------------------------------------------------------------------------------
p.formatNumber = function(frame)
Line 1,359 ⟶ 2,056:
-------------------------------------------------------------------------------
-- examine dumps the property (the unnamed parameter or pid)
-- from the item given by the parameter 'qid' (or the other unnamed parameter) -- or from the item corresponding to the current page if qid is not supplied.
-- e.g. {{#invoke:WikidataIB |examine |pid=P26 |qid=Q42}}
-- or {{#invoke:WikidataIB |examine |P26 |Q42}} or any combination of these
-- or {{#invoke:WikidataIB |examine |P26}} for the current page.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.examine = function( frame )
local args
if frame.args[1] or frame.args.pid or frame.args.qid then
else
args = frame:getParent().args
end
local par = {}
local pid = (args.pid or ""):upper()
local qid = (args.qid or ""):upper()
par[1] = mw.text.trim( args[1] or "" ):upper()
par[2] = mw.text.trim( args[2] or "" ):upper()
table.sort(par)
if par[2]:sub(1,1) == "P" then par[1], par[2] = par[2], par[1] end
if pid == "" then pid = par[1] end
if qid == "" then qid = par[2] end
if pid:sub(1,1) ~= "P" then return "No property supplied" end
if qid:sub(1,1) ~= "Q" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return "No item for this page" end
return mw.dumpObject( mw.wikibase.getAllStatements( qid, pid ) )
end
-------------------------------------------------------------------------------
-- checkvalue looks for 'val' as a wikibase-item value of a property (the unnamed parameter or pid)
-- from the item given by the parameter 'qid'
-- or from the Wikidata item associated with the current page if qid is not supplied.
-- If property is not supplied, then P31 (instance of) is assumed.
-- It returns val if found or nothing if not found.
-- e.g. {{#invoke:WikidataIB |checkvalue |val=Q5 |pid=P31 |qid=Q42}}
-- or {{#invoke:WikidataIB |checkvalue |val=Q5 |P31 |qid=Q42}}
-- or {{#invoke:WikidataIB |checkvalue |val=Q5 |qid=Q42}}
-- or {{#invoke:WikidataIB |checkvalue |val=Q5 |P31}} for the current page.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.checkvalue = function( frame )
local args
if frame.args.val then
args = frame.args
else
args = frame:getParent().args
end
local val = args.val
if not val then return nil end
local pid = mw.text.trim(args.pid or args[1] or "P31"):upper()
local qid = (args.qid or ""):upper()
if pid:sub(1,1) ~= "P" then return nil end
if qid:sub(1,1) ~= "Q" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return nil end
local stats = mw.wikibase.getAllStatements( qid, pid )
if not stats[1] then return nil end
if stats[1].mainsnak.datatype == "wikibase-item" then
for k, v in pairs( stats ) do
if v.mainsnak.snaktype == "value" and v.mainsnak.datavalue.value.id == val then
return val
end
end
end
return nil
end
-------------------------------------------------------------------------------
-- url2 takes a parameter url= that is a proper url and formats it for use in an infobox.
-- If no parameter is supplied, it returns nothing.
-- This is the equivalent of Template:URL
-- 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:
-- e.g. {{#invoke:WikidataIB |url2 |url={{wdib |P856 |qid=Q23317 |fwd=ALL |osd=no}}
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.url2 = function(frame)
local txt = frame.args.url or ""
if txt == "" then return nil end
local url, icon = txt:match("(.+) (.+)")
url = url or txt
icon = icon or ""
local prot, addr = url:match("(http[s]*://)(.+)")
prot = prot or url
addr = addr or ""
local disp, n = addr:gsub("%.", "<wbr/>%.")
return '<span class="url">[' .. prot .. addr .. " " .. disp .. "]</span> " .. icon
end
-------------------------------------------------------------------------------
-- getWebsite fetches the Official website (P856) and formats it for use in an infobox.
-- This is similar to Template:Official website but with a url displayed,
-- and it adds the "edit at Wikidata" pen icon beyond the microformat if enabled.
-- A local value will override the Wikidata value. "NONE" returns nothing.
-- e.g. {{#invoke:WikidataIB |getWebsite |qid= |noicon= |lang= |url= }}
-------------------------------------------------------------------------------
-- Dependencies: findLang(); parseParam();
-------------------------------------------------------------------------------
p.getWebsite = function(frame)
local url = frame.args.url or ""
if url:upper() == "NONE" then return nil end
local qid = frame.args.qid or ""
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return nil end
local urls = {}
local quals = {}
if url == "" then
local props = mw.wikibase.getBestStatements(qid, "P856")
for k, v in pairs(props) do
if v.mainsnak.snaktype == "value" then
urls[#urls+1] = v.mainsnak.datavalue.value
if v.qualifiers and v.qualifiers["P1065"] then
-- just take the first archive url (P1065)
local au = v.qualifiers["P1065"][1]
if au.snaktype == "value" then
quals[#urls] = au.datavalue.value
end -- test for archive url having a value
end -- test for qualifers
end -- test for website having a value
end -- loop through website(s)
else
urls[1] = url
end
if #urls == 0 then return nil end
local out = {}
for i, u in ipairs(urls) do
local link = quals[i] or u
local prot, addr = u:match("(http[s]*://)(.+)")
addr = addr or u
local disp, n = addr:gsub("%.", "<wbr/>%.")
out[#out+1] = '<span class="url">[' .. link .. " " .. disp .. "]</span>"
end
local langcode = findLang(frame.args.lang).code
local noicon = parseParam(frame.args.noicon, false)
if url == "" and not noicon then
out[#out] = out[#out] .. createicon(langcode, qid, "P856")
end
local ret = ""
if #out > 1 then
ret = mw.getCurrentFrame():expandTemplate{title = "ubl", args = out}
else
ret = out[1]
end
return ret
end
-------------------------------------------------------------------------------
-- getAllLabels fetches the set of labels and formats it for display as wikitext.
-- It takes a parameter 'qid' for arbitrary access, otherwise it uses the current page.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getAllLabels = function(frame)
local args = frame.args or frame:getParent().args or {}
local qid = args.qid
if qid == "" then qid = nil end
local entity = mw.wikibase.getEntity(qid)
if not entity then return i18n["entity-not-found"] end
local labels = entity.labels
if not labels then return i18n["labels-not-found"] end
out = {}
for k, v in pairs(labels) do
out[#out+1] = v.value .. " (" .. v.language .. ")"
end
return table.concat(out, "; ")
end
-------------------------------------------------------------------------------
-- getAllDescriptions fetches the set of descriptions and formats it for display as wikitext.
-- It takes a parameter 'qid' for arbitrary access, otherwise it uses the current page.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getAllDescriptions = function(frame)
local args = frame.args or frame:getParent().args or {}
local qid = args.qid
if qid == "" then qid = nil end
local entity = mw.wikibase.getEntity(qid)
if not entity then return i18n["entity-not-found"] end
local descriptions = entity.descriptions
if not descriptions then return i18n["descriptions-not-found"] end
out = {}
for k, v in pairs(descriptions) do
out[#out+1] = v.value .. " (" .. v.language .. ")"
end
return table.concat(out, "; ")
end
-------------------------------------------------------------------------------
-- getAllAliases fetches the set of descriptions and formats it for display as wikitext.
-- It takes a parameter 'qid' for arbitrary access, otherwise it uses the current page.
-------------------------------------------------------------------------------
-- Dependencies: none
-------------------------------------------------------------------------------
p.getAllAliases = function(frame)
local args = frame.args or frame:getParent().args or {}
local qid = args.qid
if qid == "" then qid = nil end
local entity = mw.wikibase.getEntity(qid)
if not entity then return i18n["entity-not-found"] end
local aliases = entity.aliases
if not aliases then return i18n["aliases-not-found"] end
out = {}
for k1, v1 in pairs(aliases) do
local lang = v1[1].language
local val = {}
for k1, v2 in ipairs(v1) do
val[#val+1] = v2.value
end
out[#out+1] = table.concat(val, ", ") .. " (" .. lang .. ")"
end
return table.concat(out, "; ")
end
return p
-------------------------------------------------------------------------------
-- List of exported functions
-------------------------------------------------------------------------------
-- getValue
-- getPreferredValue
-- getCoords
-- getQualifierValue
-- getValueByQual
-- getValueByLang
-- getLink
-- getLabel
-- getAT
-- getDescription
-- pageId
-- formatDate
-- ___location
-- checkBlacklist
-- emptyor
-- labelorid
-- getLang
-- findLanguage
-- getQID
-- followQid
-- siteID
-- projID
-- formatNumber
-- examine
-- checkvalue
-- url2
-- getWebsite
-------------------------------------------------------------------------------
|