Module:PornBaseDataIB: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
PeaceDeadC (talk | contribs) No edit summary |
PeaceDeadC (talk | contribs) No edit summary |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- Version: 2020-11-08 |
|||
-- Module to implement use of a blacklist and whitelist for infobox fields |
|||
-- Can take a named parameter |qid which is the PornBaseData ID for the article |
|||
-- if not supplied, it will use the PornBaseData ID associated with the current page. |
|||
-- Fields in blacklist are never to be displayed, i.e. module must return nil in all circumstances |
|||
-- Fields in whitelist return local value if it exists or the PornBaseData value otherwise |
|||
-- The name of the field that this function is called from is passed in named parameter |name |
|||
-- The name is compulsory when blacklist or whitelist is used, |
|||
-- so the module returns nil if it is not supplied. |
|||
-- blacklist is passed in named parameter |suppressfields (or |spf) |
|||
-- whitelist is passed in named parameter |fetchpornbasedata (or |fpbd) |
|||
local p = {} |
local p = {} |
||
local cdate |
|||
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:I18n/complex date, Module:ISOdate, Module:DateI18n (alternative for 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 = { |
local dp = { |
||
[6] = "millennium", |
[6] = "millennium", |
||
| Line 65: | Line 48: | ||
["Unknown"] = "Unknown", |
["Unknown"] = "Unknown", |
||
["NaN"] = "Not a number", |
["NaN"] = "Not a number", |
||
-- set the following to the name of a tracking category, |
|||
-- e.g. "[[Category:Articles with missing PornBaseData information]]", or "" to disable: |
|||
["missinginfocat"] = "[[Category:Articles with missing PornBaseData information]]", |
["missinginfocat"] = "[[Category:Articles with missing PornBaseData information]]", |
||
["editonpornbasedata"] = "Edit this on PornBaseData", |
["editonpornbasedata"] = "Edit this on PornBaseData", |
||
["latestdatequalifier"] = function (date) return "before " .. date end, |
["latestdatequalifier"] = function (date) return "before " .. date end, |
||
-- some languages, e.g. Bosnian use a period as a suffix after each number in a date |
|||
["datenumbersuffix"] = "", |
["datenumbersuffix"] = "", |
||
["list separator"] = ", ", |
["list separator"] = ", ", |
||
| Line 81: | Line 61: | ||
} |
} |
||
} |
} |
||
-- This allows an internationisation module to override the above table |
|||
if 'en' ~= mw.getContentLanguage():getCode() then |
if 'en' ~= mw.getContentLanguage():getCode() then |
||
require("Module:i18n").loadI18n("Module:PornBaseDataIB/i18n", i18n) |
require("Module:i18n").loadI18n("Module:PornBaseDataIB/i18n", i18n) |
||
end |
end |
||
-- This piece of html implements a collapsible container. Check the classes exist on your wiki. |
|||
local collapsediv = '<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}">' |
local collapsediv = '<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}">' |
||
-- Some items should not be linked. |
|||
-- Each wiki can create a list of those in Module:PornBaseDataIB/nolinks |
|||
-- It should return a table called itemsindex, containing true for each item not to be linked |
|||
local donotlink = {} |
local donotlink = {} |
||
local nolinks_exists, nolinks = pcall(mw.loadData, "Module:PornBaseDataIB/nolinks") |
local nolinks_exists, nolinks = pcall(mw.loadData, "Module:PornBaseDataIB/nolinks") |
||
| Line 98: | Line 73: | ||
end |
end |
||
-- To satisfy Wikipedia:Manual of Style/Titles, certain types of items are italicised, and others are quoted. |
|||
-- The submodule [[Module:PornBaseDataIB/titleformats]] lists the entity-ids used in 'instance of' (P1), |
|||
-- which allows this module to identify the values that should be formatted. |
|||
-- PornBaseDataIB/titleformats exports a table p.formats, which is indexed by entity-id, and contains the value " or '' |
|||
local formats = {} |
local formats = {} |
||
local titleformats_exists, titleformats = pcall(mw.loadData, "Module:PornBaseDataIB/titleformats") |
local titleformats_exists, titleformats = pcall(mw.loadData, "Module:PornBaseDataIB/titleformats") |
||
| Line 108: | Line 79: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- Private functions |
|||
------------------------------------------------------------------------------- |
|||
-- |
|||
------------------------------------------------------------------------------- |
|||
-- makeOrdinal needs to be internationalised along with the above: |
|||
-- takes cardinal number as a numeric and returns the ordinal as a string |
|||
-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local makeOrdinal = function(cardinal) |
local makeOrdinal = function(cardinal) |
||
local ordsuffix = i18n.ordinal.default |
local ordsuffix = i18n.ordinal.default |
||
| Line 128: | Line 88: | ||
ordsuffix = i18n.ordinal[3] |
ordsuffix = i18n.ordinal[3] |
||
end |
end |
||
-- In English, 1, 21, 31, etc. use 'st', but 11, 111, etc. use 'th' |
|||
-- similarly for 12 and 13, etc. |
|||
if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then |
if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then |
||
ordsuffix = i18n.ordinal.default |
ordsuffix = i18n.ordinal.default |
||
| Line 136: | Line 94: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- findLang takes a "langcode" parameter 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 findLang = function(langcode) |
||
local langobj |
local langobj |
||
| Line 161: | Line 110: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- _getItemLangCode takes a qid parameter (using the current page's qid if blank) |
|||
-- If the item for that qid has property country (P40) it looks at the first preferred value |
|||
-- If the country has an official language (P256), it looks at the first preferred value |
|||
-- If that official language has a language code (P329), it returns the first preferred value |
|||
-- Otherwise it returns nothing. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local _getItemLangCode = function(qid) |
local _getItemLangCode = function(qid) |
||
qid = mw.text.trim(qid or ""):upper() |
qid = mw.text.trim(qid or ""):upper() |
||
| Line 186: | Line 125: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- roundto takes a number (x) |
|||
-- and returns it rounded to (sf) significant figures |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local roundto = function(x, sf) |
local roundto = function(x, sf) |
||
if x == 0 then return 0 end |
if x == 0 then return 0 end |
||
| Line 203: | Line 135: | ||
local p = 10 ^ (math.floor(math.log10(x)) - sf + 1) |
local p = 10 ^ (math.floor(math.log10(x)) - sf + 1) |
||
x = math.floor(x / p + 0.5) * p * s |
x = math.floor(x / p + 0.5) * p * s |
||
-- if it's integral, cast to an integer: |
|||
if x == math.floor(x) then x = math.floor(x) end |
if x == math.floor(x) then x = math.floor(x) end |
||
return x |
return x |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- decimalToDMS takes a decimal degrees (x) with precision (p) |
|||
-- and returns degrees/minutes/seconds according to the precision |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local decimalToDMS = function(x, p) |
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 |
if not tonumber(p) then p = 1e-4 end |
||
local d = math.floor(x) |
local d = math.floor(x) |
||
local ms = (x - d) * 60 |
local ms = (x - d) * 60 |
||
if p > 0.5 then |
if p > 0.5 then |
||
if ms > 30 then d = d + 1 end |
if ms > 30 then d = d + 1 end |
||
ms = 0 |
ms = 0 |
||
| Line 226: | Line 149: | ||
local m = math.floor(ms) |
local m = math.floor(ms) |
||
local s = (ms - m) * 60 |
local s = (ms - m) * 60 |
||
if p > 0.008 then |
if p > 0.008 then |
||
if s > 30 then m = m +1 end |
if s > 30 then m = m +1 end |
||
s = 0 |
s = 0 |
||
elseif p > 0.00014 then |
elseif p > 0.00014 then |
||
s = math.floor(s + 0.5) |
s = math.floor(s + 0.5) |
||
elseif p > 0.000014 then |
elseif p > 0.000014 then |
||
s = math.floor(10 * s + 0.5) / 10 |
s = math.floor(10 * s + 0.5) / 10 |
||
elseif p > 0.0000014 then |
elseif p > 0.0000014 then |
||
s = math.floor(100 * s + 0.5) / 100 |
s = math.floor(100 * s + 0.5) / 100 |
||
else |
|||
else -- cap it at 3 dec places for now |
|||
s = math.floor(1000 * s + 0.5) / 1000 |
s = math.floor(1000 * s + 0.5) / 1000 |
||
end |
end |
||
| Line 241: | Line 164: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- decimalPrecision takes a decimal (x) with precision (p) |
|||
-- and returns x rounded approximately to the given precision |
|||
-- precision should be between 1 and 1e-6, preferably a power of 10. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local decimalPrecision = function(x, p) |
local decimalPrecision = function(x, p) |
||
local s = 1 |
local s = 1 |
||
| Line 255: | Line 170: | ||
s = -1 |
s = -1 |
||
end |
end |
||
-- if p is not supplied, pick an arbitrary precision |
|||
if not tonumber(p) then p = 1e-4 |
if not tonumber(p) then p = 1e-4 |
||
elseif p > 1 then p = 1 |
elseif p > 1 then p = 1 |
||
| Line 262: | Line 176: | ||
end |
end |
||
x = math.floor(x / p + 0.5) * p * s |
x = math.floor(x / p + 0.5) * p * s |
||
-- if it's integral, cast to an integer: |
|||
if x == math.floor(x) then x = math.floor(x) end |
if x == math.floor(x) then x = math.floor(x) end |
||
-- if it's less than 1e-4, it will be in exponent form, so return a string with 6dp |
|||
-- 9e-5 becomes 0.000090 |
|||
if math.abs(x) < 1e-4 then x = string.format("%f", x) end |
if math.abs(x) < 1e-4 then x = string.format("%f", x) end |
||
return x |
return x |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- formatDate takes a datetime of the usual format from mw.wikibase.entity:formatPropertyValues |
|||
-- like "1 August 30 BCE" as parameter 1 |
|||
-- and formats it according to the df (date format) and bc parameters |
|||
-- df = ["dmy" / "mdy" / "y"] default will be "dmy" |
|||
-- bc = ["BC" / "BCE"] default will be "BCE" |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local format_Date = function(datetime, dateformat, bc) |
local format_Date = function(datetime, dateformat, bc) |
||
local datetime = datetime or "1 August 30 BCE" |
local datetime = datetime or "1 August 30 BCE" |
||
-- chop off multiple vales and/or any hours, mins, etc. |
|||
-- keep anything before punctuation - we just want a single date: |
|||
local dateval = string.match( datetime, "[%w ]+") |
local dateval = string.match( datetime, "[%w ]+") |
||
local dateformat = string.lower(dateformat or "dmy") |
local dateformat = string.lower(dateformat or "dmy") |
||
local bc = string.upper(bc or "") |
local bc = string.upper(bc or "") |
||
-- we only want to accept two possibilities: BC or default to BCE |
|||
if bc == "BC" then |
if bc == "BC" then |
||
bc = " " .. i18n["BC"] |
bc = " " .. i18n["BC"] |
||
else |
else |
||
bc = " " .. i18n["BCE"] |
bc = " " .. i18n["BCE"] |
||
end |
end |
||
local postchrist = true |
local postchrist = true |
||
local dateparts = {} |
local dateparts = {} |
||
for word in string.gmatch(dateval, "%w+") do |
for word in string.gmatch(dateval, "%w+") do |
||
if word == "BCE" or word == "BC" then |
if word == "BCE" or word == "BC" then |
||
postchrist = false |
postchrist = false |
||
else |
else |
||
-- we'll keep the parts that are not 'BCE' in a table |
|||
dateparts[#dateparts + 1] = word |
dateparts[#dateparts + 1] = word |
||
end |
end |
||
end |
end |
||
if postchrist then bc = "" end |
if postchrist then bc = "" end |
||
local sep = " " |
local sep = " " |
||
local fdate = table.concat(dateparts, sep) |
local fdate = table.concat(dateparts, sep) |
||
-- if we have day month year, check dateformat |
|||
if #dateparts == 3 then |
if #dateparts == 3 then |
||
if dateformat == "y" then |
if dateformat == "y" then |
||
| Line 325: | Line 221: | ||
end |
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 circumstances"/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, model) |
local dateFormat = function(timestamp, dprec, df, bcf, pd, qualifiers, lang, adj, model) |
||
-- output formatting according to preferences (y/dmy/mdy/ymd) |
|||
df = (df or ""):lower() |
df = (df or ""):lower() |
||
-- if ymd is required, return the part of the timestamp in YYYY-MM-DD form |
|||
-- but apply Year zero#Astronomers fix: 1 BC = 0000; 2 BC = -0001; etc. |
|||
if df == "ymd" then |
if df == "ymd" then |
||
if timestamp:sub(1,1) == "+" then |
if timestamp:sub(1,1) == "+" then |
||
| Line 351: | Line 233: | ||
end |
end |
||
end |
end |
||
-- 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") |
timestamp = timestamp:gsub("%-00%-00T", "-01-01T") |
||
-- just in case date precision is missing |
|||
dprec = dprec or 11 |
dprec = dprec or 11 |
||
-- override more precise dates if required dateformat is year alone: |
|||
if df == "y" and dprec > 9 then dprec = 9 end |
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>11 and 11 or dprec |
||
dprec = dprec<6 and 6 or dprec |
dprec = dprec<6 and 6 or dprec |
||
-- BC format is "BC" or "BCE" |
|||
bcf = (bcf or ""):upper() |
bcf = (bcf or ""):upper() |
||
-- plaindate only needs the first letter (y/n/a) |
|||
pd = (pd or ""):sub(1,1):lower() |
pd = (pd or ""):sub(1,1):lower() |
||
if pd == "" or pd == "n" or pd == "f" or pd == "0" then pd = false end |
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 |
lang = lang or findLang().code |
||
-- set adj as empty if nil |
|||
adj = adj or "" |
adj = adj or "" |
||
-- extract the day, month, year from the timestamp |
|||
local bc = timestamp:sub(1, 1)=="-" and "BC" or "" |
local bc = timestamp:sub(1, 1)=="-" and "BC" or "" |
||
local year, month, day = timestamp:match("[+-](%d*)-(%d*)-(%d*)T") |
local year, month, day = timestamp:match("[+-](%d*)-(%d*)-(%d*)T") |
||
local iso = tonumber(year) |
local iso = tonumber(year) |
||
-- 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 == 6 then iso = math.floor( (iso - 1) / 1000 ) + 1 end |
||
if dprec == 7 then iso = math.floor( (iso - 1) / 100 ) + 1 end |
if dprec == 7 then iso = math.floor( (iso - 1) / 100 ) + 1 end |
||
| Line 383: | Line 251: | ||
if dprec == 10 then iso = year .. "-" .. month end |
if dprec == 10 then iso = year .. "-" .. month end |
||
if dprec == 11 then iso = year .. "-" .. month .. "-" .. day 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 |
local sc = not pd and qualifiers and qualifiers.P1480 |
||
if sc then |
if sc then |
||
| Line 393: | Line 260: | ||
end |
end |
||
end |
end |
||
-- deal with Julian dates: |
|||
-- no point in saying that dates before 1582 are Julian - they are by default |
|||
-- doesn't make sense for dates less precise than year |
|||
-- we can suppress it by setting |plaindate, e.g. for use in constructing categories. |
|||
local calendarmodel = "" |
local calendarmodel = "" |
||
if tonumber(year) > 1582 |
if tonumber(year) > 1582 |
||
and dprec > 8 |
and dprec > 8 |
||
and not pd |
and not pd |
||
and model == "https:// |
and model == "https://pornbasedata.com/wiki/Q219" then |
||
calendarmodel = "julian" |
calendarmodel = "julian" |
||
end |
end |
||
| Line 408: | Line 271: | ||
end |
end |
||
local fdate = cdate(calendarmodel, adj, tostring(iso), dp[dprec], bc, "", "", "", "", lang, 1) |
local fdate = cdate(calendarmodel, 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>', '') |
fdate = fdate:gsub(' <div style="display: none;">[^<]*</div>', '') |
||
-- it may also be returned wrapped in a microformat, so remove that |
|||
fdate = fdate:gsub("<[^>]*>", "") |
fdate = fdate:gsub("<[^>]*>", "") |
||
-- there may be leading zeros that we should remove |
|||
fdate = fdate:gsub("^0*", "") |
fdate = fdate:gsub("^0*", "") |
||
-- if a plain date is required, then remove any links (like BC linked) |
|||
if pd then |
if pd then |
||
fdate = fdate:gsub("%[%[.*|", ""):gsub("]]", "") |
fdate = fdate:gsub("%[%[.*|", ""):gsub("]]", "") |
||
end |
end |
||
-- if 'circa', use the abbreviated form *** internationalise later *** |
|||
fdate = fdate:gsub('circa ', '<abbr title="circa">c.</abbr> ') |
fdate = fdate:gsub('circa ', '<abbr title="circa">c.</abbr> ') |
||
-- deal with BC/BCE |
|||
if bcf == "BCE" then |
if bcf == "BCE" then |
||
fdate = fdate:gsub('BC', 'BCE') |
fdate = fdate:gsub('BC', 'BCE') |
||
end |
end |
||
-- deal with mdy format |
|||
if df == "mdy" then |
if df == "mdy" then |
||
fdate = fdate:gsub("(%d+) (%w+) (%d+)", "%2 %1, %3") |
fdate = fdate:gsub("(%d+) (%w+) (%d+)", "%2 %1, %3") |
||
end |
end |
||
-- deal with adjectival form *** internationalise later *** |
|||
if pd == "a" then |
if pd == "a" then |
||
fdate = fdate:gsub(' century', '-century') |
fdate = fdate:gsub(' century', '-century') |
||
| Line 435: | Line 290: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- parseParam takes a (string) parameter, e.g. from the list of frame arguments, |
|||
-- and makes "false", "no", and "0" into the (boolean) false |
|||
-- it makes the empty string and nil into the (boolean) value passed as default |
|||
-- allowing the parameter to be true or false by default. |
|||
-- It returns a boolean. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local parseParam = function(param, default) |
local parseParam = function(param, default) |
||
if type(param) == "boolean" then param = tostring(param) end |
if type(param) == "boolean" then param = tostring(param) end |
||
| Line 459: | Line 304: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- _getSitelink takes the qid of a PornBaseData 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) |
local _getSitelink = function(qid, wiki) |
||
qid = (qid or ""):upper() |
qid = (qid or ""):upper() |
||
| Line 483: | Line 318: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- _getCommonslink takes an optional qid of a PornBaseData entity passed as |qid= |
|||
-- It returns one of the following in order of preference: |
|||
-- the Commons sitelink of the PornBaseData entity - but not if onlycat=true and it's not a category; |
|||
-- the Commons sitelink of the topic's main category of the PornBaseData entity; |
|||
-- the Commons category of the PornBaseData entity - unless fallback=false. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getSitelink(); parseParam() |
|||
------------------------------------------------------------------------------- |
|||
local _getCommonslink = function(qid, onlycat, fallback) |
local _getCommonslink = function(qid, onlycat, fallback) |
||
qid = (qid or ""):upper() |
qid = (qid or ""):upper() |
||
| Line 502: | Line 327: | ||
if onlycat and sitelink and sitelink:sub(1,9) ~= "Category:" then sitelink = nil end |
if onlycat and sitelink and sitelink:sub(1,9) ~= "Category:" then sitelink = nil end |
||
if not sitelink then |
if not sitelink then |
||
-- check for topic's main category |
|||
local prop50 = mw.wikibase.getBestStatements(qid, "P50")[1] |
local prop50 = mw.wikibase.getBestStatements(qid, "P50")[1] |
||
if prop50 then |
if prop50 then |
||
| Line 509: | Line 333: | ||
end |
end |
||
if not sitelink then |
if not sitelink then |
||
-- check for list's main category |
|||
local prop189 = mw.wikibase.getBestStatements(qid, "P189")[1] |
local prop189 = mw.wikibase.getBestStatements(qid, "P189")[1] |
||
if prop189 then |
if prop189 then |
||
| Line 518: | Line 341: | ||
end |
end |
||
if not sitelink and fallback then |
if not sitelink and fallback then |
||
-- check for PBC category (string value) |
|||
local prop191 = mw.wikibase.getBestStatements(qid, "P191")[1] |
local prop191 = mw.wikibase.getBestStatements(qid, "P191")[1] |
||
if prop191 then |
if prop191 then |
||
| Line 528: | Line 350: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- The label in a PornBaseData item is subject to vulnerabilities |
|||
-- that an attacker might try to exploit. |
|||
-- It needs to be 'sanitised' by removing any wikitext before use. |
|||
-- If it doesn't exist, return the id for the item |
|||
-- a second (boolean) value is also returned, value is true when the label exists |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local labelOrId = function(id, lang) |
local labelOrId = function(id, lang) |
||
if lang == "default" then lang = findLang().code end |
if lang == "default" then lang = findLang().code end |
||
| Line 553: | Line 365: | ||
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 |
|||
-- dtxt is text to be used instead of label, or nil. |
|||
-- shortname is boolean switch to use P203 (short name) instead of label if true. |
|||
-- lang is the current language code. |
|||
-- uselbl is boolean switch to display the label |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: labelOrId(); donotlink[] |
|||
------------------------------------------------------------------------------- |
|||
local linkedItem = function(id, lprefix, lpostfix, prefix, postfix, dtxt, shortname, lang, uselbl) |
local linkedItem = function(id, lprefix, lpostfix, prefix, postfix, dtxt, shortname, lang, uselbl) |
||
lprefix = lprefix or "" |
lprefix = lprefix or "" |
||
lpostfix = lpostfix or "" |
lpostfix = lpostfix or "" |
||
prefix = prefix or "" |
prefix = prefix or "" |
||
postfix = postfix or "" |
postfix = postfix or "" |
||
lang = lang or " |
lang = lang or "pbc" |
||
-- see if item might need italics or quotes |
|||
local fmt = "" |
local fmt = "" |
||
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P1") ) do |
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P1") ) do |
||
if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then |
if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then |
||
fmt = formats[v.mainsnak.datavalue.value.id] |
fmt = formats[v.mainsnak.datavalue.value.id] |
||
break |
break |
||
end |
end |
||
end |
end |
||
| Line 589: | Line 384: | ||
label, islabel = dtxt, true |
label, islabel = dtxt, true |
||
elseif shortname then |
elseif shortname then |
||
-- see if there is a shortname in our language, and set label to it |
|||
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P203") ) do |
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P203") ) do |
||
if v.mainsnak.datavalue.value.language == lang then |
if v.mainsnak.datavalue.value.language == lang then |
||
label, islabel = v.mainsnak.datavalue.value.text, true |
label, islabel = v.mainsnak.datavalue.value.text, true |
||
break |
break |
||
end |
|||
end -- test for language match |
|||
end |
|||
end -- loop through values of short name |
|||
-- if we have no label set, then there was no shortname available |
|||
if not islabel then |
if not islabel then |
||
label, islabel = labelOrId(id) |
label, islabel = labelOrId(id) |
||
| Line 607: | Line 400: | ||
if sitelink then |
if sitelink then |
||
if not (dtxt or shortname) then |
if not (dtxt or shortname) then |
||
-- if sitelink and label are the same except for case, no need to process further |
|||
if sitelink:lower() ~= label:lower() then |
if sitelink:lower() ~= label:lower() then |
||
-- strip any namespace or dab from the sitelink |
|||
local pos = sitelink:find(":") or 0 |
local pos = sitelink:find(":") or 0 |
||
local slink = sitelink |
local slink = sitelink |
||
if pos > 0 then |
if pos > 0 then |
||
local prefix = sitelink:sub(1,pos-1) |
local prefix = sitelink:sub(1,pos-1) |
||
if mw.site.namespaces[prefix] then |
if mw.site.namespaces[prefix] then |
||
slink = sitelink:sub(pos+1) |
slink = sitelink:sub(pos+1) |
||
end |
end |
||
end |
end |
||
-- remove stuff after commas or inside parentheses - ie. dabs |
|||
slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "") |
slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "") |
||
-- if uselbl is false, use sitelink instead of label |
|||
if not uselbl then |
if not uselbl then |
||
-- use slink as display, preserving label case - find("^%u") is true for 1st char uppercase |
|||
if label:find("^%u") then |
if label:find("^%u") then |
||
label = slink:gsub("^(%l)", string.upper) |
label = slink:gsub("^(%l)", string.upper) |
||
| Line 637: | Line 425: | ||
end |
end |
||
elseif islabel then |
elseif islabel then |
||
local artitle = mw.title.new(label, 0) |
|||
-- no sitelink, label exists, so check if a redirect with that title exists |
|||
local artitle = mw.title.new(label, 0) -- only nil if label has invalid chars |
|||
if not donotlink[label] and artitle and artitle.redirectTarget then |
if not donotlink[label] and 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 .. fmt .. label .. fmt .. postfix .. "]]" |
disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]" |
||
else |
else |
||
-- either (donotlink is true) or (no sitelink, label exists, not redirect) |
|||
-- so output unlinked label with italics or quotes as needed |
|||
disp = prefix .. fmt .. label .. fmt .. postfix |
disp = prefix .. fmt .. label .. fmt .. postfix |
||
end |
|||
end -- test if article title exists as redirect on current Wiki |
|||
else |
else |
||
-- no sitelink and no label, so return whatever was returned from labelOrId for now |
|||
-- add tracking category [[Category:Articles with missing PornBaseData information]] |
|||
-- for enwiki, just return the tracking category |
|||
if mw.wikibase.getGlobalSiteId() == "pbcimagerepo" then |
if mw.wikibase.getGlobalSiteId() == "pbcimagerepo" then |
||
disp = i18n.missinginfocat |
disp = i18n.missinginfocat |
||
| Line 663: | Line 444: | ||
disp = "[[" .. lprefix .. "Category:" .. ccat .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]" |
disp = "[[" .. lprefix .. "Category:" .. ccat .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]" |
||
elseif sitelink then |
elseif sitelink then |
||
-- this asumes that if a sitelink exists, then a label also exists |
|||
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]" |
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]" |
||
else |
else |
||
-- no sitelink and no Commons cat, so return label from labelOrId for now |
|||
disp = prefix .. label .. postfix |
disp = prefix .. label .. postfix |
||
end |
end |
||
| Line 673: | Line 452: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- sourced takes a table representing a statement that may or may not have references |
|||
-- it looks for a reference sourced to something not containing the word "wikipedia" |
|||
-- it returns a boolean = true if it finds a sourced reference. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local sourced = function(claim) |
local sourced = function(claim) |
||
if claim.references then |
if claim.references then |
||
| Line 692: | Line 463: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- setRanks takes a flag (parameter passed) that requests the values to return |
|||
-- "b[est]" returns preferred if available, otherwise normal |
|||
-- "p[referred]" returns preferred |
|||
-- "n[ormal]" returns normal |
|||
-- "d[eprecated]" returns deprecated |
|||
-- multiple values are allowed, e.g. "preferred normal" (which is the default) |
|||
-- "best" will override the other flags, and set p and n |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
local setRanks = function(rank) |
local setRanks = function(rank) |
||
rank = (rank or ""):lower() |
rank = (rank or ""):lower() |
||
-- if nothing passed, return preferred and normal |
|||
-- if rank == "" then rank = "p n" end |
|||
local ranks = {} |
local ranks = {} |
||
for w in string.gmatch(rank, "%a+") do |
for w in string.gmatch(rank, "%a+") do |
||
| Line 715: | Line 472: | ||
end |
end |
||
end |
end |
||
-- check if "best" is requested or no ranks requested; and if so, set preferred and normal |
|||
if ranks.b or not next(ranks) then |
if ranks.b or not next(ranks) then |
||
ranks.p = true |
ranks.p = true |
||
| Line 723: | Line 479: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- parseInput processes the Q-id , the blacklist and the whitelist |
|||
-- if an input parameter is supplied, it returns that and ends the call. |
|||
-- it returns (1) either the qid or nil indicating whether or not the call should continue |
|||
-- 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) |
local parseInput = function(frame, input_parm, property_id) |
||
-- There may be a local parameter supplied, if it's blank, set it to nil |
|||
input_parm = mw.text.trim(input_parm or "") |
input_parm = mw.text.trim(input_parm or "") |
||
if input_parm == "" then input_parm = nil end |
if input_parm == "" then input_parm = nil end |
||
-- return nil if PornBaseData is not available |
|||
if not mw.wikibase then return false, input_parm end |
if not mw.wikibase then return false, input_parm end |
||
local args = frame.args |
local args = frame.args |
||
-- can take a named parameter |qid which is the PornBaseData ID for the article. |
|||
-- if it's not supplied, use the id for the current page |
|||
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 there's no PornBaseData item for the current page return nil |
|||
if not qid then return false, input_parm end |
if not qid then return false, input_parm end |
||
-- The blacklist is passed in named parameter |suppressfields |
|||
local blacklist = args.suppressfields or args.spf or "" |
local blacklist = args.suppressfields or args.spf or "" |
||
-- The whitelist is passed in named parameter |fetchpornbasedata |
|||
local whitelist = args.fetchpornbasedata or args.fpbd or "" |
local whitelist = args.fetchpornbasedata or args.fpbd or "" |
||
if whitelist == "" then whitelist = "NONE" end |
if whitelist == "" then whitelist = "NONE" end |
||
-- The name of the field that this function is called from is passed in named parameter |name |
|||
local fieldname = args.name or "" |
local fieldname = args.name or "" |
||
if blacklist ~= "" then |
if blacklist ~= "" then |
||
-- The name is compulsory when blacklist is used, so return nil if it is not supplied |
|||
if fieldname == "" then return false, nil end |
if fieldname == "" then return false, nil end |
||
-- If this field is on the blacklist, then return nil |
|||
if blacklist:find(fieldname) then return false, nil end |
if blacklist:find(fieldname) then return false, nil end |
||
end |
end |
||
-- If we got this far then we're not on the blacklist |
|||
-- The blacklist overrides any locally supplied parameter as well |
|||
-- If a non-blank input parameter was supplied return it |
|||
if input_parm then return false, input_parm end |
if input_parm then return false, input_parm end |
||
-- We can filter out non-valid properties |
|||
if property_id:sub(1,1):upper() ~="P" or property_id == "P0" then return false, nil end |
if property_id:sub(1,1):upper() ~="P" or property_id == "P0" then return false, nil end |
||
-- Otherwise see if this field is on the whitelist: |
|||
-- needs a bit more logic because find will return its second value = 0 if fieldname is "" |
|||
-- but nil if fieldname not found on whitelist |
|||
local _, found = whitelist:find(fieldname) |
local _, found = whitelist:find(fieldname) |
||
found = ((found or 0) > 0) |
found = ((found or 0) > 0) |
||
| Line 784: | Line 513: | ||
end |
end |
||
-- See what's on PornBaseData (the call always returns a table, but it may be empty): |
|||
local props = {} |
local props = {} |
||
if args.reqranks.b then |
if args.reqranks.b then |
||
| Line 794: | Line 522: | ||
return qid, props |
return qid, props |
||
end |
end |
||
-- no property on PornBaseData |
|||
return false, nil |
return false, nil |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- createicon assembles the "Edit at PornBaseData" pen icon. |
|||
-- It returns a wikitext string inside a span class="penicon" |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: i18n[]; |
|||
------------------------------------------------------------------------------- |
|||
local createicon = function(langcode, entityID, propertyID) |
local createicon = function(langcode, entityID, propertyID) |
||
local icon = " <span class='penicon'>[[" |
local icon = " <span class='penicon'>[[" |
||
-- " <span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable PornBaseData Bridge |
|||
.. i18n["filespace"] |
.. i18n["filespace"] |
||
.. ":OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" |
.. ":OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt=" |
||
.. i18n["editonpornbasedata"] |
.. i18n["editonpornbasedata"] |
||
.. "|link=https:// |
.. "|link=https://pornbasedata.com/wiki/" .. entityID |
||
.. "?uselang=" .. langcode |
.. "?uselang=" .. langcode |
||
if propertyID then icon = icon .. "#" .. propertyID end |
if propertyID then icon = icon .. "#" .. propertyID end |
||
| Line 818: | Line 537: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- assembleoutput takes the sequence table containing the property values |
|||
-- 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. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam(); |
|||
------------------------------------------------------------------------------- |
|||
local assembleoutput = function(out, args, entityID, propertyID) |
local assembleoutput = function(out, args, entityID, propertyID) |
||
-- sorted is a boolean passed to enable sorting of the values returned |
|||
-- if nothing or an empty string is passed set it false |
|||
-- if "false" or "no" or "0" is passed set it false |
|||
local sorted = parseParam(args.sorted, false) |
local sorted = parseParam(args.sorted, false) |
||
-- noicon is a boolean passed to suppress the trailing "edit at PornBaseData" icon |
|||
-- for use when the value is processed further by the infobox |
|||
-- if nothing or an empty string is passed set it false |
|||
-- if "false" or "no" or "0" is passed set it false |
|||
local noic = parseParam(args.noicon, false) |
local noic = parseParam(args.noicon, false) |
||
-- list is the name of a template that a list of multiple values is passed through |
|||
-- examples include "hlist" and "ubl" |
|||
-- setting it to "prose" produces something like "1, 2, 3, and 4" |
|||
local list = args.list or "" |
local list = args.list or "" |
||
-- sep is a string that is used to separate multiple returned values |
|||
-- if nothing or an empty string is passed set it to the default |
|||
-- any double-quotes " are stripped out, so that spaces may be passed |
|||
-- e.g. |sep=" - " |
|||
local sepdefault = i18n["list separator"] |
local sepdefault = i18n["list separator"] |
||
local separator = args.sep or "" |
local separator = args.sep or "" |
||
| Line 855: | Line 552: | ||
end |
end |
||
-- collapse is a number that determines the maximum number of returned values |
|||
-- before the output is collapsed. |
|||
-- Zero or not a number result in no collapsing (default becomes 0). |
|||
local collapse = tonumber(args.collapse) or 0 |
local collapse = tonumber(args.collapse) or 0 |
||
-- replacetext (rt) is a string that is returned instead of any non-empty PornBaseData value |
|||
-- this is useful for tracking and debugging |
|||
local replacetext = mw.text.trim(args.rt or args.replacetext or "") |
local replacetext = mw.text.trim(args.rt or args.replacetext or "") |
||
-- if there's anything to return, then return a list |
|||
-- comma-separated by default, but may be specified by the sep parameter |
|||
-- optionally specify a hlist or ubl or a prose list, etc. |
|||
local strout |
local strout |
||
if #out > 0 then |
if #out > 0 then |
||
if sorted then table.sort(out) end |
if sorted then table.sort(out) end |
||
-- if there's something to display and a pen icon is wanted, add it the end of the last value |
|||
local hasdisplay = false |
local hasdisplay = false |
||
for i, v in ipairs(out) do |
for i, v in ipairs(out) do |
||
| Line 892: | Line 580: | ||
end |
end |
||
else |
else |
||
strout = nil |
strout = nil |
||
end |
end |
||
if replacetext ~= "" and strout then strout = replacetext end |
if replacetext ~= "" and strout then strout = replacetext end |
||
| Line 898: | Line 586: | ||
end |
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, localMedia, 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 Qid. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam(); labelOrId(); i18n[]; dateFormat(); |
|||
-- roundto(); decimalPrecision(); decimalToDMS(); linkedItem(); |
|||
------------------------------------------------------------------------------- |
|||
local rendersnak = function(propval, args, linked, lpre, lpost, pre, post, uabbr, filter) |
local rendersnak = function(propval, args, linked, lpre, lpost, pre, post, uabbr, filter) |
||
lpre = lpre or "" |
lpre = lpre or "" |
||
| Line 921: | Line 592: | ||
post = post or "" |
post = post or "" |
||
args.lang = args.lang or findLang().code |
args.lang = args.lang or findLang().code |
||
-- allow values to display a fixed text instead of label |
|||
local dtxt = args.displaytext or args.dt |
local dtxt = args.displaytext or args.dt |
||
if dtxt == "" then dtxt = nil end |
if dtxt == "" then dtxt = nil end |
||
-- switch to use display of short name (P203) instead of label |
|||
local shortname = args.shortname or args.sn |
local shortname = args.shortname or args.sn |
||
shortname = parseParam(shortname, false) |
shortname = parseParam(shortname, false) |
||
| Line 933: | Line 602: | ||
local dv = snak.datavalue |
local dv = snak.datavalue |
||
dv = dv and dv.value |
dv = dv and dv.value |
||
-- value and monolingual text language code returned |
|||
local val, mlt |
local val, mlt |
||
if propval.rank and not args.reqranks[propval.rank:sub(1, 1)] then |
if propval.rank and not args.reqranks[propval.rank:sub(1, 1)] then |
||
elseif snak.snaktype == "somevalue" then |
|||
-- val is nil: value has a rank that isn't requested |
|||
------------------------------------ |
|||
elseif snak.snaktype == "somevalue" then -- value is unknown |
|||
val = i18n["Unknown"] |
val = i18n["Unknown"] |
||
elseif snak.snaktype == "novalue" then |
|||
------------------------------------ |
|||
elseif |
elseif dtype == "wikibase-item" then |
||
-- 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 |
local qnumber = dv.id |
||
if linked then |
if linked then |
||
val = linkedItem(qnumber, lpre, lpost, pre, post, dtxt, shortname, args.lang, uselbl) |
val = linkedItem(qnumber, lpre, lpost, pre, post, dtxt, shortname, args.lang, uselbl) |
||
else |
|||
else -- no link wanted so check for display-text, otherwise test for lang code |
|||
local label, islabel |
local label, islabel |
||
if dtxt then |
if dtxt then |
||
| Line 961: | Line 623: | ||
end |
end |
||
val = pre .. label .. post |
val = pre .. label .. post |
||
end |
|||
end -- test for link required |
|||
elseif dtype == "time" then |
|||
------------------------------------ |
|||
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 |
|||
-- |
|||
-- Here we can check whether args.df has a value |
|||
-- If not, use code from Module:Sandbox/RexxS/Getdateformat to set it from templates like {{Use mdy dates}} |
|||
val = dateFormat(dv.time, dv.precision, args.df, args.bc, args.pd, propval.qualifiers, args.lang, "", dv.calendarmodel) |
val = dateFormat(dv.time, dv.precision, args.df, args.bc, args.pd, propval.qualifiers, args.lang, "", dv.calendarmodel) |
||
------------------------------------ |
|||
-- data types which are strings: |
|||
elseif dtype == "localMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then |
elseif dtype == "localMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then |
||
-- localMedia or external-id or string or url |
|||
-- all have mainsnak.datavalue.value as string |
|||
if (lpre == "" or lpre == ":") and lpost == "" then |
if (lpre == "" or lpre == ":") and lpost == "" then |
||
-- don't link if no linkpre/postfix or linkprefix is just ":" |
|||
val = pre .. dv .. post |
val = pre .. dv .. post |
||
elseif dtype == "external-id" then |
elseif dtype == "external-id" then |
||
| Line 988: | Line 633: | ||
else |
else |
||
val = "[[" .. lpre .. dv .. lpost .. "|" .. pre .. dv .. post .. "]]" |
val = "[[" .. lpre .. dv .. lpost .. "|" .. pre .. dv .. post .. "]]" |
||
end |
|||
end -- check for link requested (i.e. either linkprefix or linkpostfix exists) |
|||
------------------------------------ |
|||
-- data types which are quantities: |
|||
elseif dtype == "quantity" then |
elseif dtype == "quantity" then |
||
-- quantities have mainsnak.datavalue.value.amount and mainsnak.datavalue.value.unit |
|||
-- |
|||
-- implement a switch to turn on/off numerical formatting later |
|||
local fnum = true |
local fnum = true |
||
-- |
|||
-- a switch to turn on/off conversions - only for en-wiki |
|||
local conv = parseParam(args.conv or args.convert, false) |
local conv = parseParam(args.conv or args.convert, false) |
||
-- if we have conversions, we won't have formatted numbers or scales |
|||
if conv then |
if conv then |
||
uabbr = true |
uabbr = true |
||
| Line 1,005: | Line 642: | ||
args.scale = "0" |
args.scale = "0" |
||
end |
end |
||
-- |
|||
-- a switch to turn on/off showing units, default is true |
|||
local showunits = parseParam(args.su or args.showunits, true) |
local showunits = parseParam(args.su or args.showunits, true) |
||
-- |
|||
-- convert amount to a number |
|||
local amount = tonumber(dv.amount) or i18n["NaN"] |
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 sc = tostring(args.scale or ""):sub(1,1):lower() |
||
local scale |
local scale |
||
if sc == "a" then |
if sc == "a" then |
||
-- automatic scaling |
|||
if amount > 1e15 then |
if amount > 1e15 then |
||
scale = 12 |
scale = 12 |
||
| Line 1,035: | Line 665: | ||
local factor = 10^scale |
local factor = 10^scale |
||
amount = amount / factor |
amount = amount / factor |
||
-- ranges: |
|||
local range = "" |
local range = "" |
||
-- check if upper and/or lower bounds are given and significant |
|||
local upb = tonumber(dv.upperBound) |
local upb = tonumber(dv.upperBound) |
||
local lowb = tonumber(dv.lowerBound) |
local lowb = tonumber(dv.lowerBound) |
||
if upb and lowb then |
if upb and lowb then |
||
-- differences rounded to 2 sig fig: |
|||
local posdif = roundto(upb - amount, 2) / factor |
local posdif = roundto(upb - amount, 2) / factor |
||
local negdif = roundto(amount - lowb, 2) / factor |
local negdif = roundto(amount - lowb, 2) / factor |
||
upb, lowb = amount + posdif, amount - negdif |
upb, lowb = amount + posdif, amount - negdif |
||
-- round scaled numbers to integers or 4 sig fig |
|||
if (scale > 0 or sc == "a") then |
if (scale > 0 or sc == "a") then |
||
if amount < 1e4 then |
if amount < 1e4 then |
||
| Line 1,055: | Line 681: | ||
if fnum then amount = args.langobj:formatNum( amount ) end |
if fnum then amount = args.langobj:formatNum( amount ) end |
||
if posdif ~= negdif then |
if posdif ~= negdif then |
||
-- non-symmetrical |
|||
range = " +" .. posdif .. " -" .. negdif |
range = " +" .. posdif .. " -" .. negdif |
||
elseif posdif ~= 0 then |
elseif posdif ~= 0 then |
||
-- symmetrical and non-zero |
|||
range = " ±" .. posdif |
range = " ±" .. posdif |
||
else |
else |
||
-- otherwise range is zero, so leave it as "" |
|||
end |
end |
||
else |
else |
||
-- round scaled numbers to integers or 4 sig fig |
|||
if (scale > 0 or sc == "a") then |
if (scale > 0 or sc == "a") then |
||
if amount < 1e4 then |
if amount < 1e4 then |
||
| Line 1,074: | Line 696: | ||
if fnum then amount = args.langobj:formatNum( amount ) end |
if fnum then amount = args.langobj:formatNum( amount ) end |
||
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 unit = "" |
||
local usep = "" |
local usep = "" |
||
| Line 1,086: | Line 705: | ||
if uname ~= "" then usep, unit = " ", uname end |
if uname ~= "" then usep, unit = " ", uname end |
||
if uabbr then |
if uabbr then |
||
-- see if there's a unit symbol (P5061) |
|||
local unitsymbols = mw.wikibase.getBestStatements(unitqid, "P5061") |
local unitsymbols = mw.wikibase.getBestStatements(unitqid, "P5061") |
||
-- construct fallback table, add local lang and multiple languages |
|||
local fbtbl = mw.language.getFallbacksFor( args.lang ) |
local fbtbl = mw.language.getFallbacksFor( args.lang ) |
||
table.insert( fbtbl, 1, args.lang ) |
table.insert( fbtbl, 1, args.lang ) |
||
| Line 1,101: | Line 718: | ||
end |
end |
||
if found then break end |
if found then break end |
||
end |
end |
||
end |
|||
end -- loop through values of P5061 |
|||
if found then usep, unit = " ", usym end |
if found then usep, unit = " ", usym end |
||
end |
end |
||
end |
end |
||
-- format display: |
|||
if conv then |
if conv then |
||
if range == "" then |
if range == "" then |
||
| Line 1,118: | Line 734: | ||
val = amount .. range .. i18n.multipliers[scale] .. usep .. unit |
val = amount .. range .. i18n.multipliers[scale] .. usep .. unit |
||
end |
end |
||
------------------------------------ |
|||
-- datatypes which are global coordinates: |
|||
elseif dtype == "globe-coordinate" then |
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) |
local form = (args.format or ""):lower():sub(1,3) |
||
if form ~= "dec" then form = "dms" end |
if form ~= "dec" then form = "dms" end |
||
-- |
|||
-- show parameter allows just the latitude, or just the longitude, or both |
|||
-- to be returned as a signed decimal, ignoring the format parameter. |
|||
local show = (args.show or ""):lower() |
local show = (args.show or ""):lower() |
||
if show ~= "longlat" then show = show:sub(1,3) end |
if show ~= "longlat" then show = show:sub(1,3) end |
||
| Line 1,174: | Line 779: | ||
end |
end |
||
end |
end |
||
elseif dtype == "monolingualtext" then |
|||
------------------------------------ |
|||
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 |
val = pre .. dv.text .. post |
||
mlt = dv.language |
mlt = dv.language |
||
------------------------------------ |
|||
else |
else |
||
-- some other data type so write a specific handler |
|||
val = "unknown data type: " .. dtype |
val = "unknown data type: " .. dtype |
||
end |
|||
end -- of datatype/unknown value/sourced check |
|||
return val, mlt |
return val, mlt |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- propertyvalueandquals takes a property object, the arguments passed from frame, |
|||
-- and a qualifier propertyID. |
|||
-- It returns a sequence (table) of values representing the values of that property |
|||
-- 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) |
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 |
|||
-- if nothing or an empty string is passed set it true |
|||
local onlysrc = parseParam(args.onlysourced or args.osd, true) |
local onlysrc = parseParam(args.onlysourced or args.osd, true) |
||
-- linked is a a boolean that enables the link to a local page via sitelink |
|||
-- if nothing or an empty string is passed set it true |
|||
local linked = parseParam(args.linked, true) |
local linked = parseParam(args.linked, true) |
||
-- prefix is a string that may be nil, empty (""), or a string of characters |
|||
-- this is prefixed to each value |
|||
-- useful when when multiple values are returned |
|||
-- any double-quotes " are stripped out, so that spaces may be passed |
|||
local prefix = (args.prefix or ""):gsub('"', '') |
local prefix = (args.prefix or ""):gsub('"', '') |
||
-- postfix is a string that may be nil, empty (""), or a string of characters |
|||
-- this is postfixed to each value |
|||
-- useful when when multiple values are returned |
|||
-- any double-quotes " are stripped out, so that spaces may be passed |
|||
local postfix = (args.postfix or ""):gsub('"', '') |
local postfix = (args.postfix or ""):gsub('"', '') |
||
-- linkprefix is a string that may be nil, empty (""), or a string of characters |
|||
-- this creates a link and is then prefixed to each value |
|||
-- 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('"', '') |
local lprefix = (args.linkprefix or args.lp or ""):gsub('"', '') |
||
-- linkpostfix is a string that may be nil, empty (""), or a string of characters |
|||
-- this is postfixed to each value when linking is enabled with lprefix |
|||
-- useful when when multiple values are returned |
|||
-- any double-quotes " are stripped out, so that spaces may be passed |
|||
local lpostfix = (args.linkpostfix or ""):gsub('"', '') |
local lpostfix = (args.linkpostfix or ""):gsub('"', '') |
||
-- wdlinks is a boolean passed to enable links to PornBaseData when no article exists |
|||
-- if nothing or an empty string is passed set it false |
|||
local wdl = parseParam(args.wdlinks or args.wdl, false) |
local wdl = parseParam(args.wdlinks or args.wdl, false) |
||
-- 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) |
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) |
local qualsonly = parseParam(args.qualsonly or args.qo, false) |
||
-- maxvals is a string that may be nil, empty (""), or a number |
|||
-- this determines how many items may be returned when multiple values are available |
|||
-- setting it = 1 is useful where the returned string is used within another call, e.g. image |
|||
local maxvals = tonumber(args.maxvals) or 0 |
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 pd = args.plaindate or args.pd or "no" |
||
args.pd = pd |
args.pd = pd |
||
-- allow qualifiers to have a different date format; default to year |
|||
args.qdf = args.qdf or args.qualifierdateformat or args.df or "y" |
args.qdf = args.qdf or args.qualifierdateformat or args.df or "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 = qualID or "" |
qualID = qualID or "" |
||
-- capitalise list of wanted qualifiers and substitute "DATES" |
|||
qualID = qualID:upper():gsub("DATES", "P580, P582") |
qualID = qualID:upper():gsub("DATES", "P580, P582") |
||
local allflag = (qualID == "ALL") |
local allflag = (qualID == "ALL") |
||
-- create table of wanted qualifiers as key |
|||
local qwanted = {} |
local qwanted = {} |
||
-- create sequence of wanted qualifiers |
|||
local qorder = {} |
local qorder = {} |
||
for q in mw.text.gsplit(qualID, "%p") do |
for q in mw.text.gsplit(qualID, "%p") do |
||
local qtrim = mw.text.trim(q) |
local qtrim = mw.text.trim(q) |
||
if qtrim ~= "" then |
if qtrim ~= "" then |
||
| Line 1,276: | Line 828: | ||
end |
end |
||
end |
end |
||
-- qsep is the output separator for rendering qualifier list |
|||
local qsep = (args.qsep or ""):gsub('"', '') |
local qsep = (args.qsep or ""):gsub('"', '') |
||
-- qargs are the arguments to supply to assembleoutput() |
|||
local qargs = { |
local qargs = { |
||
["osd"] = "false", |
["osd"] = "false", |
||
| Line 1,299: | Line 849: | ||
} |
} |
||
-- all proper values of a PornBaseData 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 |
local datatype = objproperty[1].datatype or objproperty[1].mainsnak.datatype |
||
-- out[] holds the a list of returned values for this property |
|||
-- mlt[] holds the language code if the datatype is monolingual text |
|||
local out = {} |
local out = {} |
||
local mlt = {} |
local mlt = {} |
||
| Line 1,311: | Line 857: | ||
local hasvalue = true |
local hasvalue = true |
||
if (onlysrc and not sourced(v)) then |
if (onlysrc and not sourced(v)) then |
||
-- no value: it isn't sourced when onlysourced=true |
|||
hasvalue = false |
hasvalue = false |
||
else |
else |
||
local val, lcode = rendersnak(v, args, linked, lprefix, lpostfix, prefix, postfix, uabbr) |
local val, lcode = rendersnak(v, args, linked, lprefix, lpostfix, prefix, postfix, uabbr) |
||
if not val then |
if not val then |
||
hasvalue = false |
hasvalue = false |
||
elseif qualsonly and qualID then |
elseif qualsonly and qualID then |
||
-- suppress value returned: only qualifiers are requested |
|||
else |
else |
||
out[#out+1], mlt[#out+1] = val, lcode |
out[#out+1], mlt[#out+1] = val, lcode |
||
| Line 1,324: | Line 868: | ||
end |
end |
||
-- See if qualifiers are to be returned: |
|||
local snak = v.mainsnak or v |
local snak = v.mainsnak or v |
||
if hasvalue and v.qualifiers and qualID ~= "" and snak.snaktype~="novalue" then |
if hasvalue and v.qualifiers and qualID ~= "" and snak.snaktype~="novalue" then |
||
-- collect all wanted qualifier values returned in qlist, indexed by propertyID |
|||
local qlist = {} |
local qlist = {} |
||
local timestart, timeend = "", "" |
local timestart, timeend = "", "" |
||
-- loop through qualifiers |
|||
for k1, v1 in pairs(v.qualifiers) do |
for k1, v1 in pairs(v.qualifiers) do |
||
if allflag or qwanted[k1] then |
if allflag or qwanted[k1] then |
||
| Line 1,342: | Line 883: | ||
qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "after") |
qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "after") |
||
elseif k1 == "P34" then |
elseif k1 == "P34" then |
||
timestart = propertyvalueandquals(v1, qargs)[1] or "" |
timestart = propertyvalueandquals(v1, qargs)[1] or "" |
||
elseif k1 == "P41" then |
elseif k1 == "P41" then |
||
timeend = propertyvalueandquals(v1, qargs)[1] or "" |
timeend = propertyvalueandquals(v1, qargs)[1] or "" |
||
else |
else |
||
local q = assembleoutput(propertyvalueandquals(v1, qargs), qargs) |
local q = assembleoutput(propertyvalueandquals(v1, qargs), qargs) |
||
-- we already deal with circa via 'sourcing circumstances' if the datatype was time |
|||
-- circa may be either linked or unlinked *** internationalise later *** |
|||
if datatype ~= "time" or q ~= "circa" and not (type(q) == "string" and q:find("circa]]")) then |
if datatype ~= "time" or q ~= "circa" and not (type(q) == "string" and q:find("circa]]")) then |
||
qlist[k1] = q |
qlist[k1] = q |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
end |
||
-- set date separator |
|||
local t = timestart .. timeend |
local t = timestart .. timeend |
||
-- *** internationalise date separators later *** |
|||
local dsep = "–" |
local dsep = "–" |
||
if t:find("%s") or t:find(" ") then dsep = " – " end |
if t:find("%s") or t:find(" ") then dsep = " – " end |
||
-- set the order for the list of qualifiers returned; start time and end time go last |
|||
if next(qlist) then |
if next(qlist) then |
||
local qlistout = {} |
local qlistout = {} |
||
| Line 1,388: | Line 924: | ||
end |
end |
||
end |
end |
||
end |
|||
end -- of test for qualifiers wanted |
|||
if maxvals > 0 and #out >= maxvals then break end |
if maxvals > 0 and #out >= maxvals then break end |
||
end |
|||
end -- of for each value loop |
|||
-- we need to pick one value to return if the datatype was "monolingualtext" |
|||
-- if there's only one value, use that |
|||
-- otherwise look through the fallback languages for a match |
|||
if datatype == "monolingualtext" and #out >1 then |
if datatype == "monolingualtext" and #out >1 then |
||
lang = mw.text.split( lang, '-', true )[1] |
lang = mw.text.split( lang, '-', true )[1] |
||
| Line 1,409: | Line 942: | ||
break |
break |
||
end |
end |
||
end |
|||
end -- loop through values of property |
|||
end |
|||
end -- loop through fallback languages |
|||
if found then |
if found then |
||
-- replace output table with a table containing the best value |
|||
out = { bestval } |
out = { bestval } |
||
else |
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] } |
out = { out[1] } |
||
end |
end |
||
| Line 1,423: | Line 953: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- Common code for p.getValueByQual and p.getValueByLang |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
local _getvaluebyqual = function(frame, qualID, checkvalue) |
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 "") |
local propertyID = mw.text.trim(frame.args[1] or "") |
||
if propertyID == "" then return "no property supplied" end |
if propertyID == "" then return "no property supplied" end |
||
| Line 1,437: | Line 960: | ||
if qualID == "" then return "no qualifier 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) |
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true) |
||
-- set the requested ranks flags |
|||
frame.args.reqranks = setRanks(frame.args.rank) |
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.langobj = findLang(frame.args.lang) |
||
frame.args.lang = frame.args.langobj.code |
frame.args.lang = frame.args.langobj.code |
||
| Line 1,452: | Line 969: | ||
local args = frame.args |
local args = frame.args |
||
-- check for locally supplied parameter in second unnamed parameter |
|||
-- success means no local parameter and the property exists |
|||
local qid, props = parseInput(frame, args[2], propertyID) |
local qid, props = parseInput(frame, args[2], propertyID) |
||
| Line 1,467: | Line 982: | ||
if qid then |
if qid then |
||
local out = {} |
local out = {} |
||
-- Scan through the values of the property |
|||
-- we want something like property is "pronunciation audio" in propertyID |
|||
-- with a qualifier like "language of work or name" in qualID |
|||
-- whose value has the required ID, like "British English", in qval |
|||
for k1, v1 in ipairs(props) do |
for k1, v1 in ipairs(props) do |
||
if v1.mainsnak.snaktype == "value" then |
if v1.mainsnak.snaktype == "value" then |
||
-- check if it has the right qualifier |
|||
local v1q = v1.qualifiers |
local v1q = v1.qualifiers |
||
if v1q and v1q[qualID] then |
if v1q and v1q[qualID] 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 |
|||
-- so see if matches the required value |
|||
-- We'll only deal with wikibase-items and strings for now |
|||
if v1q[qualID][1].datatype == "wikibase-item" then |
if v1q[qualID][1].datatype == "wikibase-item" then |
||
if checkvalue(v1q[qualID][1].datavalue.value.id) then |
if checkvalue(v1q[qualID][1].datavalue.value.id) then |
||
| Line 1,489: | Line 996: | ||
end |
end |
||
end |
end |
||
end |
end |
||
end |
|||
end -- of check for matching required value and has qualifiers |
|||
else |
else |
||
return nil |
return nil |
||
end |
end |
||
end |
|||
end -- of loop through values of propertyID |
|||
return assembleoutput(out, frame.args, qid, propertyID) |
return assembleoutput(out, frame.args, qid, propertyID) |
||
else |
else |
||
return props |
return props |
||
end |
|||
end -- of test for success |
|||
return nil |
return nil |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- _location takes Q-id and follows P196 (location) |
|||
-- or P49 (located in the administrative territorial entity) or P202 (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) |
local _location = function(qid, first, skip) |
||
first = parseParam(first, false) |
first = parseParam(first, false) |
||
| Line 1,527: | Line 1,023: | ||
local proptbl = mw.wikibase.getBestStatements(qid, v1) |
local proptbl = mw.wikibase.getBestStatements(qid, v1) |
||
if #proptbl > 1 then |
if #proptbl > 1 then |
||
-- there is more than one higher location |
|||
local prevP49, prevP49id |
local prevP49, prevP49id |
||
if prevqid ~= "Q0" then |
if prevqid ~= "Q0" then |
||
| Line 1,538: | Line 1,033: | ||
parttbl = v2.qualifiers and v2.qualifiers.P200 |
parttbl = v2.qualifiers and v2.qualifiers.P200 |
||
if parttbl then |
if parttbl then |
||
-- this higher location has qualifier 'applies to part' (P200) |
|||
for i3, v3 in ipairs(parttbl) do |
for i3, v3 in ipairs(parttbl) do |
||
if v3.snaktype == "value" and v3.datavalue.value.id == prevqid then |
if v3.snaktype == "value" and v3.datavalue.value.id == prevqid then |
||
-- it has a value equal to the previous location |
|||
prop = proptbl[i2] |
prop = proptbl[i2] |
||
break |
break |
||
end |
end |
||
end |
|||
end -- of loop through values of 'applies to part' |
|||
else |
else |
||
-- there's no qualifier 'applies to part' (P200) |
|||
-- so check if the previous location had a P49 that matches this alternate |
|||
if qid == prevP49id then |
if qid == prevP49id then |
||
prop = proptbl[i2] |
prop = proptbl[i2] |
||
break |
break |
||
end |
|||
end -- of test for matching previous P49 |
|||
end |
end |
||
end |
|||
end -- of loop through parent locations |
|||
-- fallback to second value if match not found |
|||
prop = prop or proptbl[2] |
prop = prop or proptbl[2] |
||
elseif #proptbl > 0 then |
elseif #proptbl > 0 then |
||
| Line 1,563: | Line 1,053: | ||
end |
end |
||
-- check if it's an instance of (P1) a country or sovereign state |
|||
-- and terminate the chain if it is |
|||
local inst = mw.wikibase.getAllStatements(qid, "P1") |
local inst = mw.wikibase.getAllStatements(qid, "P1") |
||
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.value.id |
||
-- stop if it's a country (or a country within the United Kingdom if skip is true) |
|||
if instid == "Q210" or instid == "Q1041" or (skip and instid == "Q3336843") then |
if instid == "Q210" or instid == "Q1041" or (skip and instid == "Q3336843") then |
||
prop = nil |
prop = nil |
||
break |
break |
||
end |
end |
||
| Line 1,577: | Line 1,064: | ||
end |
end |
||
-- get the name of this location and update qid to point to the parent location |
|||
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, ":", "", "", "") |
out[#out+1] = linkedItem(qid, ":", "", "", "") |
||
end |
end |
||
qid, prevqid = prop.mainsnak.datavalue.value.id, qid |
qid, prevqid = prop.mainsnak.datavalue.value.id, qid |
||
else |
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 |
|||
local prop203 = mw.wikibase.getAllStatements(qid, "P203") |
local prop203 = mw.wikibase.getAllStatements(qid, "P203") |
||
-- if there's a short name and this isn't the only item |
|||
if prop203[1] and (#out > 0)then |
if prop203[1] and (#out > 0)then |
||
local shortname |
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(prop203) do |
for k, v in pairs(prop203) do |
||
if v.mainsnak.datavalue.value.language == langcode then |
if v.mainsnak.datavalue.value.language == langcode then |
||
| Line 1,600: | Line 1,081: | ||
end |
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 |
if shortname ~= "USA" then |
||
out[#out+1] = shortname or labelOrId(qid) |
out[#out+1] = shortname or labelOrId(qid) |
||
| Line 1,608: | Line 1,087: | ||
end |
end |
||
else |
else |
||
-- no shortname, so just add the label |
|||
local loc = labelOrId(qid) |
local loc = labelOrId(qid) |
||
-- exceptions go here: |
|||
if loc == "United States of America" then |
if loc == "United States of America" then |
||
out[#out+1] = "United States" |
out[#out+1] = "United States" |
||
| Line 1,620: | Line 1,097: | ||
end |
end |
||
count = count + 1 |
count = count + 1 |
||
until finished or count >= 10 |
until finished or count >= 10 |
||
-- remove the first location if not required |
|||
if not first then table.remove(out, 1) end |
if not first then table.remove(out, 1) end |
||
-- we might have duplicate text for consecutive locations, so remove them |
|||
if #out > 2 then |
if #out > 2 then |
||
local plain = {} |
local plain = {} |
||
for i, v in ipairs(out) do |
for i, v in ipairs(out) do |
||
-- strip any links |
|||
plain[i] = v:gsub("^%[%[[^|]*|", ""):gsub("]]$", "") |
plain[i] = v:gsub("^%[%[[^|]*|", ""):gsub("]]$", "") |
||
end |
end |
||
| Line 1,635: | Line 1,109: | ||
repeat |
repeat |
||
if plain[idx] == plain[idx-1] then |
if plain[idx] == plain[idx-1] then |
||
-- duplicate found |
|||
local removeidx = 0 |
local removeidx = 0 |
||
if (plain[idx] ~= out[idx]) and (plain[idx-1] == out[idx-1]) then |
if (plain[idx] ~= out[idx]) and (plain[idx-1] == out[idx-1]) then |
||
-- only second one is linked, so drop the first |
|||
removeidx = idx - 1 |
removeidx = idx - 1 |
||
elseif (plain[idx] == out[idx]) and (plain[idx-1] ~= out[idx-1]) then |
elseif (plain[idx] == out[idx]) and (plain[idx-1] ~= out[idx-1]) then |
||
-- only first one is linked, so drop the second |
|||
removeidx = idx |
removeidx = idx |
||
else |
else |
||
-- pick one |
|||
removeidx = idx - (os.time()%2) |
removeidx = idx - (os.time()%2) |
||
end |
end |
||
| Line 1,657: | Line 1,127: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- _getsumofparts scans the property 'has part' (P173) for values matching a list. |
|||
-- The list (args.vlist) consists of a string of Qids separated by spaces or any usual punctuation. |
|||
-- If the matched values have a qualifer 'quantity' (P204), those quantites are summed. |
|||
-- The sum is returned as a number (i.e. 0 if none) |
|||
-- a table of arguments is supplied implementing the usual parameters. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: setRanks; parseParam; parseInput; sourced; assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
local _getsumofparts = function(args) |
local _getsumofparts = function(args) |
||
local vallist = (args.vlist or ""):upper() |
local vallist = (args.vlist or ""):upper() |
||
| Line 1,695: | Line 1,155: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
------------------------------------------------------------------------------- |
|||
-- Public functions |
|||
------------------------------------------------------------------------------- |
|||
------------------------------------------------------------------------------- |
|||
-- _getValue makes the functionality of getValue available to other modules |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: setRanks; parseInput; propertyvalueandquals; assembleoutput; parseParam; sourced; |
|||
-- labelOrId; i18n.latestdatequalifier; format_Date; makeOrdinal; roundto; decimalPrecision; decimalToDMS; |
|||
------------------------------------------------------------------------------- |
|||
p._getValue = function(args) |
p._getValue = function(args) |
||
-- parameter sets for commonly used groups of parameters |
|||
local paraset = tonumber(args.ps or args.parameterset or 0) |
local paraset = tonumber(args.ps or args.parameterset or 0) |
||
if paraset == 1 then |
if paraset == 1 then |
||
-- a common setting |
|||
args.rank = "best" |
args.rank = "best" |
||
args.fetchpornbasedata = "ALL" |
args.fetchpornbasedata = "ALL" |
||
| Line 1,716: | Line 1,163: | ||
args.noicon = "true" |
args.noicon = "true" |
||
elseif paraset == 2 then |
elseif paraset == 2 then |
||
-- equivalent to raw |
|||
args.rank = "best" |
args.rank = "best" |
||
args.fetchpornbasedata = "ALL" |
args.fetchpornbasedata = "ALL" |
||
| Line 1,724: | Line 1,170: | ||
args.pd = "true" |
args.pd = "true" |
||
elseif paraset == 3 then |
elseif paraset == 3 then |
||
-- third set goes here |
|||
end |
end |
||
-- implement eid parameter |
|||
local eid = args.eid |
local eid = args.eid |
||
if eid == "" then |
if eid == "" then |
||
| Line 1,739: | Line 1,183: | ||
args.reqranks = setRanks(args.rank) |
args.reqranks = setRanks(args.rank) |
||
-- replacetext (rt) is a string that is returned instead of any non-empty PornBaseData value |
|||
-- this is useful for tracking and debugging, so we set fetchpornbasedata=ALL to fill the whitelist |
|||
local replacetext = mw.text.trim(args.rt or args.replacetext or "") |
local replacetext = mw.text.trim(args.rt or args.replacetext or "") |
||
if replacetext ~= "" then |
if replacetext ~= "" then |
||
| Line 1,751: | Line 1,193: | ||
if not entityid then |
if not entityid then |
||
return props |
return props |
||
end |
end |
||
-- qual is a string containing the property ID of the qualifier(s) to be returned |
|||
-- if qual == "ALL" then all qualifiers returned |
|||
-- if qual == "DATES" then qualifiers P580 (start time) and P582 (end time) returned |
|||
-- if nothing or an empty string is passed set it nil -> no qualifiers returned |
|||
local qualID = mw.text.trim(args.qual or ""):upper() |
local qualID = mw.text.trim(args.qual or ""):upper() |
||
if qualID == "" then qualID = nil end |
if qualID == "" then qualID = nil end |
||
-- set a language object and code in the args table |
|||
args.langobj = findLang(args.lang) |
args.langobj = findLang(args.lang) |
||
args.lang = args.langobj.code |
args.lang = args.langobj.code |
||
-- table 'out' stores the return value(s): |
|||
local out = propertyvalueandquals(props, args, qualID) |
local out = propertyvalueandquals(props, args, qualID) |
||
-- format the table of values and return it as a string: |
|||
return assembleoutput(out, args, entityid, propertyID) |
return assembleoutput(out, args, entityid, propertyID) |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getValue is used to get the value(s) of a property |
|||
-- The property ID is passed as the first unnamed parameter and is required. |
|||
-- A locally supplied parameter may optionaly be supplied as the second unnamed parameter. |
|||
-- The function will now also return qualifiers if parameter qual is supplied |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getValue; setRanks; parseInput; propertyvalueandquals; assembleoutput; parseParam; sourced; |
|||
-- labelOrId; i18n.latestdatequalifier; format_Date; makeOrdinal; roundto; decimalPrecision; decimalToDMS; |
|||
------------------------------------------------------------------------------- |
|||
p.getValue = function(frame) |
p.getValue = function(frame) |
||
local args= frame.args |
local args= frame.args |
||
| Line 1,792: | Line 1,217: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getPreferredValue is used to get a value, |
|||
-- (or a comma separated list of them if multiple values exist). |
|||
-- If preferred ranks are set, it will return those values, otherwise values with normal ranks |
|||
-- now redundant to getValue with |rank=best |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: p.getValue; setRanks; parseInput; propertyvalueandquals; assembleoutput; |
|||
-- parseParam; sourced; labelOrId; i18n.latestdatequalifier; format_Date; |
|||
-- makeOrdinal; roundto; decimalPrecision; decimalToDMS; |
|||
------------------------------------------------------------------------------- |
|||
p.getPreferredValue = function(frame) |
p.getPreferredValue = function(frame) |
||
frame.args.rank = "best" |
frame.args.rank = "best" |
||
| Line 1,808: | Line 1,222: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getCoords is used to get coordinates for display in an infobox |
|||
-- whitelist and blacklist are implemented |
|||
-- optional 'display' parameter is allowed, defaults to "inline, title" |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: setRanks(); parseInput(); decimalPrecision(); |
|||
------------------------------------------------------------------------------- |
|||
p.getCoords = function(frame) |
p.getCoords = function(frame) |
||
local propertyID = "P48" |
local propertyID = "P48" |
||
-- if there is a 'display' parameter supplied, use it |
|||
-- otherwise default to "inline, title" |
|||
local disp = frame.args.display or "" |
local disp = frame.args.display or "" |
||
if disp == "" then |
if disp == "" then |
||
| Line 1,826: | Line 1,230: | ||
end |
end |
||
-- there may be a format parameter to switch from deg/min/sec to decimal degrees |
|||
-- default is deg/min/sec |
|||
-- decimal degrees needs |format = dec |
|||
local form = (frame.args.format or ""):lower():sub(1,3) |
local form = (frame.args.format or ""):lower():sub(1,3) |
||
if form ~= "dec" then |
if form ~= "dec" then |
||
| Line 1,834: | Line 1,235: | ||
end |
end |
||
-- just deal with best values |
|||
frame.args.reqranks = setRanks("best") |
frame.args.reqranks = setRanks("best") |
||
local qid, props = parseInput(frame, frame.args[1], propertyID) |
local qid, props = parseInput(frame, frame.args[1], propertyID) |
||
if not qid then |
if not qid then |
||
return props |
return props |
||
else |
else |
||
local dv = props[1].mainsnak.datavalue.value |
local dv = props[1].mainsnak.datavalue.value |
||
| Line 1,848: | Line 1,248: | ||
lat_long["display"] = disp |
lat_long["display"] = disp |
||
lat_long["format"] = form |
lat_long["format"] = form |
||
-- invoke template Coord with the values stored in the table |
|||
return frame:expandTemplate{title = 'coord', args = lat_long} |
return frame:expandTemplate{title = 'coord', args = lat_long} |
||
end |
end |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getQualifierValue is used to get a formatted value of a qualifier |
|||
-- |
|||
-- The call needs: a property (the unnamed parameter or 1=) |
|||
-- a target value for that property (pval=) |
|||
-- a qualifier for that target value (qual=) |
|||
-- The usual whitelisting and blacklisting of the property is implemented |
|||
-- The boolean onlysourced= parameter can be set to return nothing |
|||
-- 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) |
p.getQualifierValue = function(frame) |
||
-- The property ID that will have a qualifier is the first unnamed parameter |
|||
local propertyID = mw.text.trim(frame.args[1] or "") |
local propertyID = mw.text.trim(frame.args[1] or "") |
||
-- The value of the property we want to match whose qualifier value is to be returned |
|||
-- is passed in named parameter |pval= |
|||
local propvalue = frame.args.pval |
local propvalue = frame.args.pval |
||
-- The property ID of the qualifier |
|||
-- whose value is to be returned is passed in named parameter |qual= |
|||
local qualifierID = frame.args.qual |
local qualifierID = frame.args.qual |
||
-- onlysourced is a boolean passed to return qualifiers |
|||
-- 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) |
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true) |
||
-- set a language object and language code in the frame.args table |
|||
frame.args.langobj = findLang(frame.args.lang) |
frame.args.langobj = findLang(frame.args.lang) |
||
frame.args.lang = frame.args.langobj.code |
frame.args.lang = frame.args.langobj.code |
||
-- set the requested ranks flags |
|||
frame.args.reqranks = setRanks(frame.args.rank) |
frame.args.reqranks = setRanks(frame.args.rank) |
||
-- 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) |
local qid, props = parseInput(frame, frame.args[2], propertyID) |
||
if qid then |
if qid then |
||
local out = {} |
local out = {} |
||
-- Scan through the values of the property |
|||
-- we want something like property is P793, significant event (in propertyID) |
|||
-- whose value is something like Q385378, construction (in propvalue) |
|||
-- then we can return the value(s) of a qualifier such as P580, start time (in qualifierID) |
|||
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) |
|||
-- 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 |
|||
-- which matches the target, so find the value(s) of the qualifier we want |
|||
local quals = v1.qualifiers[qualifierID] |
local quals = v1.qualifiers[qualifierID] |
||
if quals then |
if quals then |
||
-- can't reference qualifer, so set onlysourced = "no" (not boolean) |
|||
local qargs = frame.args |
local qargs = frame.args |
||
qargs.onlysourced = "no" |
qargs.onlysourced = "no" |
||
| Line 1,922: | Line 1,283: | ||
end |
end |
||
end |
end |
||
end |
end |
||
end |
|||
end -- of check for matching required value and has qualifiers |
|||
end |
|||
end -- of check for wikibase entity |
|||
end |
|||
end -- of loop through values of propertyID |
|||
return assembleoutput(out, frame.args, qid, propertyID) |
return assembleoutput(out, frame.args, qid, propertyID) |
||
else |
else |
||
return props |
return props |
||
end |
|||
end -- of test for success |
|||
return nil |
return nil |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getSumOfParts scans the property 'has part' for values matching a list. |
|||
-- The list is passed in parameter vlist. |
|||
-- It consists of a string of Qids separated by spaces or any usual punctuation. |
|||
-- If the matched values have a qualifier 'quantity', those quantities are summed. |
|||
-- The sum is returned as a number or nothing if zero. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getsumofparts; |
|||
------------------------------------------------------------------------------- |
|||
p.getSumOfParts = function(frame) |
p.getSumOfParts = function(frame) |
||
local sum = _getsumofparts(frame.args) |
local sum = _getsumofparts(frame.args) |
||
| Line 1,949: | Line 1,300: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getValueByQual gets the value of a property which has a qualifier with a given entity value |
|||
-- The call needs: |
|||
-- a property ID (the unnamed parameter or 1=Pxxx) |
|||
-- the ID of a qualifier for that property (qualID=Pyyy) |
|||
-- either the Wikibase-entity ID of a value for that qualifier (qvalue=Qzzz) |
|||
-- or a string value for that qualifier (qvalue=abc123) |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getvaluebyqual; parseParam; setRanks; parseInput; sourced; |
|||
-- assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getValueByQual = function(frame) |
p.getValueByQual = function(frame) |
||
local qualID = frame.args.qualID |
local qualID = frame.args.qualID |
||
-- The Q-id of the value for the qualifier we want to match is in named parameter |qvalue= |
|||
local qval = frame.args.qvalue or "" |
local qval = frame.args.qvalue or "" |
||
if qval == "" then return "no qualifier value supplied" end |
if qval == "" then return "no qualifier value supplied" end |
||
| Line 1,973: | Line 1,310: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getValueByLang gets the value of a property which has a qualifier P407 |
|||
-- ("language of work or name") whose value has the given language code |
|||
-- The call needs: |
|||
-- a property ID (the unnamed parameter or 1=Pxxx) |
|||
-- the MediaWiki language code to match the language (lang=xx[-yy]) |
|||
-- (if no code is supplied, it uses the default language) |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getvaluebyqual; parseParam; setRanks; parseInput; sourced; assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getValueByLang = function(frame) |
p.getValueByLang = function(frame) |
||
-- The language code for the qualifier we want to match is in named parameter |lang= |
|||
local langcode = findLang(frame.args.lang).code |
local langcode = findLang(frame.args.lang).code |
||
local function checkLanguage(id) |
local function checkLanguage(id) |
||
-- id should represent a language like "British English" |
|||
-- it should have string property "Wikimedia language code" |
|||
-- qlcode will be a table: |
|||
local qlcode = mw.wikibase.getBestStatements(id, "P329") |
local qlcode = mw.wikibase.getBestStatements(id, "P329") |
||
if (#qlcode > 0) and (qlcode[1].mainsnak.datavalue.value == langcode) then |
if (#qlcode > 0) and (qlcode[1].mainsnak.datavalue.value == langcode) then |
||
| Line 2,000: | Line 1,321: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getValueByRefSource gets the value of a property which has a reference "stated in" (P248) |
|||
-- whose value has the given entity-ID. |
|||
-- 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) |
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() |
local propertyID = mw.text.trim(frame.args[1] or ""):upper() |
||
if propertyID == "" then return "no property supplied" end |
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() |
local qval = (frame.args.match or ""):upper() |
||
if qval == "" then qval = "Q21540096" end |
if qval == "" then qval = "Q21540096" end |
||
| Line 2,025: | Line 1,333: | ||
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true) |
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true) |
||
-- set the requested ranks flags |
|||
frame.args.reqranks = setRanks(frame.args.rank) |
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.langobj = findLang(frame.args.lang) |
||
frame.args.lang = frame.args.langobj.code |
frame.args.lang = frame.args.langobj.code |
||
| Line 2,036: | Line 1,342: | ||
local uabbr = parseParam(frame.args.uabbr or frame.args.unitabbr, false) |
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) |
local qid, props = parseInput(frame, frame.args[2], propertyID) |
||
| Line 2,051: | Line 1,356: | ||
out[#out+1], mlt[#out+1] = rendersnak(v1, frame.args, linked, "", "", "", "", uabbr, unit) |
out[#out+1], mlt[#out+1] = rendersnak(v1, frame.args, linked, "", "", "", "", uabbr, unit) |
||
if not mlt[#out] then |
if not mlt[#out] then |
||
-- we only need one match per property value |
|||
-- unless datatype was monolingual text |
|||
break |
break |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
|||
end -- of test that references exist |
|||
end |
end |
||
end |
|||
end -- of loop through values of propertyID |
|||
if #mlt > 0 then |
if #mlt > 0 then |
||
local langcode = frame.args.lang |
local langcode = frame.args.lang |
||
| Line 2,076: | Line 1,379: | ||
break |
break |
||
end |
end |
||
end |
|||
end -- loop through values of property |
|||
end |
|||
end -- loop through fallback languages |
|||
if found then |
if found then |
||
-- replace output table with a table containing the best value |
|||
out = { bestval } |
out = { bestval } |
||
else |
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] } |
out = { out[1] } |
||
end |
end |
||
| Line 2,089: | Line 1,389: | ||
return assembleoutput(out, frame.args, qid, propertyID) |
return assembleoutput(out, frame.args, qid, propertyID) |
||
else |
else |
||
return props |
return props |
||
end |
|||
end -- of test for success |
|||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getPropertyIDs takes most of the usual parameters. |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented. |
|||
-- It returns the Entity-IDs (Qids) of the values of a property if it is a Wikibase-Entity. |
|||
-- Otherwise it returns nothing. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getPropertyIDs = function(frame) |
p.getPropertyIDs = function(frame) |
||
local args = frame.args |
local args = frame.args |
||
| Line 2,107: | Line 1,398: | ||
args.langobj = findLang(args.lang) |
args.langobj = findLang(args.lang) |
||
args.lang = args.langobj.code |
args.lang = args.langobj.code |
||
-- change default for noicon to true |
|||
args.noicon = tostring(parseParam(args.noicon or "", true)) |
args.noicon = tostring(parseParam(args.noicon or "", true)) |
||
local f = {} |
local f = {} |
||
| Line 2,113: | Line 1,403: | ||
local pid = mw.text.trim(args[1] or ""):upper() |
local pid = mw.text.trim(args[1] or ""):upper() |
||
-- get the qid and table of claims for the property, or nothing and the local value passed |
|||
local qid, props = parseInput(f, args[2], pid) |
local qid, props = parseInput(f, args[2], pid) |
||
if not qid then return props end |
if not qid then return props end |
||
| Line 2,136: | Line 1,425: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getQualifierIDs takes most of the usual parameters. |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented. |
|||
-- It takes a property-id as the first unnamed parameter, and an optional parameter qlist |
|||
-- which is a list of qualifier property-ids to search for (default is "ALL") |
|||
-- It returns the Entity-IDs (Qids) of the values of a property if it is a Wikibase-Entity. |
|||
-- Otherwise it returns nothing. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getQualifierIDs = function(frame) |
p.getQualifierIDs = function(frame) |
||
local args = frame.args |
local args = frame.args |
||
| Line 2,152: | Line 1,430: | ||
args.langobj = findLang(args.lang) |
args.langobj = findLang(args.lang) |
||
args.lang = args.langobj.code |
args.lang = args.langobj.code |
||
-- change default for noicon to true |
|||
args.noicon = tostring(parseParam(args.noicon or "", true)) |
args.noicon = tostring(parseParam(args.noicon or "", true)) |
||
local f = {} |
local f = {} |
||
| Line 2,158: | Line 1,435: | ||
local pid = mw.text.trim(args[1] or ""):upper() |
local pid = mw.text.trim(args[1] or ""):upper() |
||
-- get the qid and table of claims for the property, or nothing and the local value passed |
|||
local qid, props = parseInput(f, args[2], pid) |
local qid, props = parseInput(f, args[2], pid) |
||
if not qid then return props end |
if not qid then return props end |
||
if not props[1] then return nil end |
if not props[1] then return nil end |
||
-- get the other parameters |
|||
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,182: | Line 1,457: | ||
if v2.datatype == "wikibase-item" and v2.snaktype == "value" then |
if v2.datatype == "wikibase-item" and v2.snaktype == "value" then |
||
out[#out+1] = v2.datavalue.value.id |
out[#out+1] = v2.datavalue.value.id |
||
end |
end |
||
end |
|||
end -- of loop through qualifier values |
|||
end |
end |
||
end |
|||
end -- of loop through qualifiers |
|||
end |
|||
end -- of test for qualifiers |
|||
end |
|||
end -- of test for rank value, sourced, and value exists |
|||
if maxvals > 0 and #out >= maxvals then break end |
if maxvals > 0 and #out >= maxvals then break end |
||
end |
|||
end -- of loop through property values |
|||
return assembleoutput(out, args, qid, pid) |
return assembleoutput(out, args, qid, pid) |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getPropOfProp takes two propertyIDs: prop1 and prop2 (as well as the usual parameters) |
|||
-- If the value(s) of prop1 are of type "wikibase-item" then it returns the value(s) of prop2 |
|||
-- of each of those wikibase-items. |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p._getPropOfProp = function(args) |
p._getPropOfProp = function(args) |
||
-- parameter sets for commonly used groups of parameters |
|||
local paraset = tonumber(args.ps or args.parameterset or 0) |
local paraset = tonumber(args.ps or args.parameterset or 0) |
||
if paraset == 1 then |
if paraset == 1 then |
||
-- a common setting |
|||
args.rank = "best" |
args.rank = "best" |
||
args.fetchpornbasedata = "ALL" |
args.fetchpornbasedata = "ALL" |
||
| Line 2,213: | Line 1,477: | ||
args.noicon = "true" |
args.noicon = "true" |
||
elseif paraset == 2 then |
elseif paraset == 2 then |
||
-- equivalent to raw |
|||
args.rank = "best" |
args.rank = "best" |
||
args.fetchpornbasedata = "ALL" |
args.fetchpornbasedata = "ALL" |
||
| Line 2,221: | Line 1,484: | ||
args.pd = "true" |
args.pd = "true" |
||
elseif paraset == 3 then |
elseif paraset == 3 then |
||
-- third set goes here |
|||
end |
end |
||
| Line 2,257: | Line 1,519: | ||
out[#out+1] = assembleoutput(out2, args, qid2, pid2) |
out[#out+1] = assembleoutput(out2, args, qid2, pid2) |
||
end |
end |
||
end |
|||
end -- of test for valid property1 value |
|||
end |
|||
end -- of test for sourced |
|||
if maxvals > 0 and #out >= maxvals then break end |
if maxvals > 0 and #out >= maxvals then break end |
||
end |
|||
end -- of loop through values of property1 |
|||
return assembleoutput(out, args, qid1, pid1) |
return assembleoutput(out, args, qid1, pid1) |
||
end |
end |
||
| Line 2,274: | Line 1,536: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getAwardCat takes most of the usual parameters. If the item has values of P206 (award received), |
|||
-- then it examines each of those awards for P207 (category for recipients of this award). |
|||
-- If it exists, it returns the corresponding category, |
|||
-- with the item's P734 (family name) as sort key, or no sort key if there is no family name. |
|||
-- The sort key may be overridden by the parameter |sortkey (alias |sk). |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getAwardCat = function(frame) |
p.getAwardCat = function(frame) |
||
frame.args.reqranks = setRanks(frame.args.rank) |
frame.args.reqranks = setRanks(frame.args.rank) |
||
| Line 2,294: | Line 1,545: | ||
local pid2 = args.prop2 or "P207" |
local pid2 = args.prop2 or "P207" |
||
if pid1 == "" or pid2 == "" then return nil end |
if pid1 == "" or pid2 == "" then return nil end |
||
-- locally supplied value: |
|||
local localval = mw.text.trim(args[1] or "") |
local localval = mw.text.trim(args[1] or "") |
||
local qid1, statements1 = parseInput(frame, localval, pid1) |
local qid1, statements1 = parseInput(frame, localval, pid1) |
||
if not qid1 then return localval end |
if not qid1 then return localval end |
||
-- linkprefix (strip quotes) |
|||
local lp = (args.linkprefix or args.lp or ""):gsub('"', '') |
local lp = (args.linkprefix or args.lp or ""):gsub('"', '') |
||
-- sort key (strip quotes, hyphens and periods): |
|||
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '') |
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '') |
||
-- family name: |
|||
local famname = "" |
local famname = "" |
||
if sk == "" then |
if sk == "" then |
||
| Line 2,308: | Line 1,555: | ||
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or "" |
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or "" |
||
famname = mw.wikibase.getSitelink(p186id) or "" |
famname = mw.wikibase.getSitelink(p186id) or "" |
||
-- strip namespace and disambigation |
|||
local pos = famname:find(":") or 0 |
local pos = famname:find(":") or 0 |
||
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "") |
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "") |
||
| Line 2,335: | Line 1,581: | ||
local qid3 = statements2[1].mainsnak.datavalue.value.id |
local qid3 = statements2[1].mainsnak.datavalue.value.id |
||
local sitelink = mw.wikibase.getSitelink(qid3) |
local sitelink = mw.wikibase.getSitelink(qid3) |
||
-- if there's no local sitelink, create the sitelink from English label |
|||
if not sitelink then |
if not sitelink then |
||
local lbl = mw.wikibase.getLabelByLang(qid3, " |
local lbl = mw.wikibase.getLabelByLang(qid3, "pbc") |
||
if lbl then |
if lbl then |
||
if lbl:sub(1,9) == "Category:" then |
if lbl:sub(1,9) == "Category:" then |
||
| Line 2,353: | Line 1,598: | ||
else |
else |
||
out[#out+1] = "[[" .. lp .. sitelink .. "]]" |
out[#out+1] = "[[" .. lp .. sitelink .. "]]" |
||
end |
end |
||
end |
end |
||
end |
end |
||
end |
|||
end -- of test for wikibase item has a value |
|||
end |
|||
end -- of test for sourced |
|||
if maxvals > 0 and #out >= maxvals then break end |
if maxvals > 0 and #out >= maxvals then break end |
||
end |
|||
end -- of loop through values of property1 |
|||
return assembleoutput(out, args, qid1, pid1) |
return assembleoutput(out, args, qid1, pid1) |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getIntersectCat takes most of the usual parameters. |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented |
|||
-- It takes two properties, |prop1 and |prop2 (e.g. occupation and country of citizenship) |
|||
-- Each property's value is a wiki-base entity |
|||
-- For each value of the first parameter (ranks implemented) it fetches the value's main category |
|||
-- and then each value of the second parameter (possibly substituting a simpler description) |
|||
-- then it returns all of the categories representing the intersection of those properties, |
|||
-- (e.g. Category:Actors from Canada). A joining term may be supplied (e.g. |join=from). |
|||
-- The item's P734 (family name) is the sort key, or no sort key if there is no family name. |
|||
-- The sort key may be overridden by the parameter |sortkey (alias |sk). |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; propertyvalueandquals assembleoutput; |
|||
------------------------------------------------------------------------------- |
|||
p.getIntersectCat = function(frame) |
p.getIntersectCat = function(frame) |
||
frame.args.reqranks = setRanks(frame.args.rank) |
frame.args.reqranks = setRanks(frame.args.rank) |
||
| Line 2,392: | Line 1,622: | ||
local qid, statements2 = parseInput(frame, "", pid2) |
local qid, statements2 = parseInput(frame, "", pid2) |
||
if not qid then return nil end |
if not qid then return nil end |
||
-- topics like countries may have different names in categories from their label in PornBaseData |
|||
local subs_exists, subs = pcall(mw.loadData, "Module:PornBaseDataIB/subs") |
local subs_exists, subs = pcall(mw.loadData, "Module:PornBaseDataIB/subs") |
||
local join = args.join or "" |
local join = args.join or "" |
||
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 |
||
-- linkprefix (strip quotes) |
|||
local lp = (args.linkprefix or args.lp or ""):gsub('"', '') |
local lp = (args.linkprefix or args.lp or ""):gsub('"', '') |
||
-- sort key (strip quotes, hyphens and periods): |
|||
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '') |
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '') |
||
-- family name: |
|||
local famname = "" |
local famname = "" |
||
if sk == "" then |
if sk == "" then |
||
| Line 2,407: | Line 1,633: | ||
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or "" |
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or "" |
||
famname = mw.wikibase.getSitelink(p186id) or "" |
famname = mw.wikibase.getSitelink(p186id) or "" |
||
-- strip namespace and disambigation |
|||
local pos = famname:find(":") or 0 |
local pos = famname:find(":") or 0 |
||
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "") |
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "") |
||
| Line 2,418: | Line 1,643: | ||
for k, v in ipairs(statements1) do |
for k, v in ipairs(statements1) do |
||
if not onlysrc or sourced(v) then |
if not onlysrc or sourced(v) then |
||
-- get the ID representing the value of the property |
|||
local pvalID = (v.mainsnak.snaktype == "value") and v.mainsnak.datavalue.value.id |
local pvalID = (v.mainsnak.snaktype == "value") and v.mainsnak.datavalue.value.id |
||
if pvalID then |
if pvalID then |
||
-- get the topic's main category (P50) for that entity |
|||
local p50 = mw.wikibase.getBestStatements(pvalID, "P50")[1] |
local p50 = mw.wikibase.getBestStatements(pvalID, "P50")[1] |
||
if p50 and p50.mainsnak.snaktype == "value" then |
if p50 and p50.mainsnak.snaktype == "value" then |
||
local tmcID = p50.mainsnak.datavalue.value.id |
local tmcID = p50.mainsnak.datavalue.value.id |
||
-- use sitelink or the English label for the cat |
|||
local cat = mw.wikibase.getSitelink(tmcID) |
local cat = mw.wikibase.getSitelink(tmcID) |
||
if not cat then |
if not cat then |
||
local lbl = mw.wikibase.getLabelByLang(tmcID, " |
local lbl = mw.wikibase.getLabelByLang(tmcID, "pbc") |
||
if lbl then |
if lbl then |
||
if lbl:sub(1,9) == "Category:" then |
if lbl:sub(1,9) == "Category:" then |
||
| Line 2,438: | Line 1,660: | ||
end |
end |
||
cat1[#cat1+1] = cat |
cat1[#cat1+1] = cat |
||
end |
|||
end -- of test for topic's main category exists |
|||
end |
|||
end -- of test for property has vaild value |
|||
end |
|||
end -- of test for sourced |
|||
if maxvals > 0 and #cat1 >= maxvals then break end |
if maxvals > 0 and #cat1 >= maxvals then break end |
||
end |
end |
||
| Line 2,461: | Line 1,683: | ||
else |
else |
||
out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "]]" |
out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "]]" |
||
end |
|||
end -- of check for sort keys |
|||
end |
end |
||
end |
end |
||
| Line 2,468: | Line 1,690: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- qualsToTable takes most of the usual parameters. |
|||
-- The usual whitelisting, blacklisting, onlysourced, etc. are implemented. |
|||
-- A qid may be given, and the first unnamed parameter is the property ID, which is of type wikibase item. |
|||
-- It takes a list of qualifier property IDs as |quals= |
|||
-- For a given qid and property, it creates the rows of an html table, |
|||
-- each row being a value of the property (optionally only if the property matches the value in |pval= ) |
|||
-- each cell being the first value of the qualifier corresponding to the list in |quals |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; setRanks; parseInput; sourced; |
|||
------------------------------------------------------------------------------- |
|||
p.qualsToTable = function(frame) |
p.qualsToTable = function(frame) |
||
local args = frame.args |
local args = frame.args |
||
| Line 2,499: | Line 1,709: | ||
local pval = args.pval or "" |
local pval = args.pval or "" |
||
local qplist = mw.text.split(quals, "%p") |
local qplist = mw.text.split(quals, "%p") |
||
for i, v in ipairs(qplist) do |
for i, v in ipairs(qplist) do |
||
qplist[i] = mw.text.trim(v):upper() |
qplist[i] = mw.text.trim(v):upper() |
||
end |
end |
||
| Line 2,511: | Line 1,721: | ||
local emptycell = args.emptycell or " " |
local emptycell = args.emptycell or " " |
||
-- construct a 2-D array of qualifier values in qvals |
|||
local qvals = {} |
local qvals = {} |
||
for i, v in ipairs(props) do |
for i, v in ipairs(props) do |
||
| Line 2,522: | Line 1,731: | ||
local qval = {} |
local qval = {} |
||
local vqualifiers = v.qualifiers or {} |
local vqualifiers = v.qualifiers or {} |
||
-- go through list of wanted qualifier properties |
|||
for i1, v1 in ipairs(qplist) do |
for i1, v1 in ipairs(qplist) do |
||
-- check for that property ID in the statement's qualifiers |
|||
local qv, qtype |
local qv, qtype |
||
if vqualifiers[v1] then |
if vqualifiers[v1] then |
||
| Line 2,547: | Line 1,754: | ||
end |
end |
||
end |
end |
||
-- record either the value or a placeholder |
|||
qval[i1] = qv or emptycell |
qval[i1] = qv or emptycell |
||
end |
|||
end -- of loop through list of qualifiers |
|||
-- add the list of qualifier values as a "row" in the main list |
|||
qvals[#qvals+1] = qval |
qvals[#qvals+1] = qval |
||
end |
end |
||
end |
|||
end -- of for each value loop |
|||
local out = {} |
local out = {} |
||
| Line 2,562: | Line 1,767: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getGlobe takes an optional qid of a PornBaseData entity passed as |qid= |
|||
-- otherwise it uses the linked item for the current page. |
|||
-- If returns the Qid of the globe used in P625 (coordinate location), |
|||
-- or nil if there isn't one. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.getGlobe = function(frame) |
p.getGlobe = function(frame) |
||
local qid = frame.args.qid or frame.args[1] or "" |
local qid = frame.args.qid or frame.args[1] or "" |
||
| Line 2,582: | Line 1,778: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getCommonsLink takes an optional qid of a PornBaseData entity passed as |qid= |
|||
-- It returns one of the following in order of preference: |
|||
-- the Commons sitelink of the linked PornBaseData item; |
|||
-- the Commons sitelink of the topic's main category of the linked PornBaseData item; |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getCommonslink(); _getSitelink(); parseParam() |
|||
------------------------------------------------------------------------------- |
|||
p.getCommonsLink = function(frame) |
p.getCommonsLink = function(frame) |
||
local oc = frame.args.onlycat or frame.args.onlycategories |
local oc = frame.args.onlycat or frame.args.onlycategories |
||
| Line 2,597: | Line 1,784: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getSitelink takes the qid of a PornBaseData 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) |
p.getSiteLink = function(frame) |
||
return _getSitelink(frame.args.qid, frame.args.wiki or mw.text.trim(frame.args[1] or "")) |
return _getSitelink(frame.args.qid, frame.args.wiki or mw.text.trim(frame.args[1] or "")) |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getLink has the qid of a PornBaseData entity passed as the first unnamed parameter or as |qid= |
|||
-- If there is a sitelink to an article on the local Wiki, it returns a link to the article |
|||
-- with the PornBaseData label as the displayed text. |
|||
-- 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) |
p.getLink = function(frame) |
||
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
||
| Line 2,633: | Line 1,800: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getLabel has the qid of a PornBaseData entity passed as the first unnamed parameter or as |qid= |
|||
-- It returns the PornBaseData 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) |
p.getLabel = function(frame) |
||
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
||
| Line 2,650: | Line 1,809: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- label has the qid of a PornBaseData entity passed as the first unnamed parameter or as |qid= |
|||
-- if no qid is supplied, it uses the qid associated with the current page. |
|||
-- It returns the PornBaseData label for the local language as plain text. |
|||
-- If there is no label in the local language, it returns nil. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.label = function(frame) |
p.label = function(frame) |
||
local qid = mw.text.trim(frame.args[1] or frame.args.qid or "") |
local qid = mw.text.trim(frame.args[1] or frame.args.qid or "") |
||
| Line 2,669: | Line 1,819: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getAT (Article Title) |
|||
-- has the qid of a PornBaseData entity passed as the first unnamed parameter or as |qid= |
|||
-- If there is a sitelink to an article on the local Wiki, it returns the sitelink as plain text. |
|||
-- If there is no sitelink or qid supplied, it returns nothing. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.getAT = function(frame) |
p.getAT = function(frame) |
||
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "") |
||
| Line 2,684: | Line 1,825: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getDescription has the qid of a PornBaseData entity passed as |qid= |
|||
-- (it defaults to the associated qid of the current article if omitted) |
|||
-- and a local parameter passed as the first unnamed parameter. |
|||
-- Any local parameter passed (other than "PornBaseData" or "none") becomes the return value. |
|||
-- It returns the article description for the PornBaseData entity if the local parameter is "PornBaseData". |
|||
-- Nothing is returned if the description doesn't exist or "none" is passed as the local parameter. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.getDescription = function(frame) |
p.getDescription = function(frame) |
||
local desc = mw.text.trim(frame.args[1] or "") |
local desc = mw.text.trim(frame.args[1] or "") |
||
| Line 2,708: | Line 1,838: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getAliases has the qid of a PornBaseData entity passed as |qid= |
|||
-- (it defaults to the associated qid of the current article if omitted) |
|||
-- and a local parameter passed as the first unnamed parameter. |
|||
-- It implements blacklisting and whitelisting with a field name of "alias" by default. |
|||
-- Any local parameter passed becomes the return value. |
|||
-- Otherwise it returns the aliases for the PornBaseData entity with the usual list options. |
|||
-- Nothing is returned if the aliases do not exist. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: findLang(); assembleoutput() |
|||
------------------------------------------------------------------------------- |
|||
p.getAliases = function(frame) |
p.getAliases = function(frame) |
||
local args = frame.args |
local args = frame.args |
||
| Line 2,762: | Line 1,880: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- pageId returns the page id (entity ID, Qnnn) of the current page |
|||
-- returns nothing if the page is not connected to PornBaseData |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.pageId = function(frame) |
p.pageId = function(frame) |
||
return mw.wikibase.getEntityIdForCurrentPage() |
return mw.wikibase.getEntityIdForCurrentPage() |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- formatDate is a wrapper to export the private function format_Date |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: format_Date(); |
|||
------------------------------------------------------------------------------- |
|||
p.formatDate = function(frame) |
p.formatDate = function(frame) |
||
return format_Date(frame.args[1], frame.args.df, frame.args.bc) |
return format_Date(frame.args[1], frame.args.df, frame.args.bc) |
||
end |
end |
||
p.getImageLegend = function(frame) |
|||
local id = frame.args.id |
|||
if id and (#id == 0) then |
|||
id = nil |
|||
end |
|||
local lang = frame.args.lang |
|||
if (not lang) or (#lang < 2) then |
|||
lang = mw.language.getContentLanguage().code |
|||
end |
|||
local input_parm = mw.text.trim(frame.args[1] or "") |
|||
if input_parm == "FETCH_WIKIDATA" then |
|||
local ent = mw.wikibase.getEntity(id) |
|||
local imgs |
|||
if ent and ent.claims then |
|||
imgs = ent.claims.P470 |
|||
end |
|||
local imglbl |
|||
if imgs then |
|||
for k1, v1 in pairs(imgs) do |
|||
if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P523 then |
|||
local imglbls = v1.qualifiers.P523 |
|||
for k2, v2 in pairs(imglbls) do |
|||
if v2.datavalue.value.language == lang then |
|||
imglbl = v2.datavalue.value.text |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if (not imglbl) then |
|||
for k1, v1 in pairs(imgs) do |
|||
if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P523 then |
|||
local imglbls = v1.qualifiers.P523 |
|||
for k2, v2 in pairs(imglbls) do |
|||
if v2.datavalue.value.language == lang then |
|||
imglbl = v2.datavalue.value.text |
|||
break |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
return imglbl |
|||
else |
|||
return input_parm |
|||
end |
|||
end |
|||
------------------------------------------------------------------------------- |
|||
-- 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 |
|||
-- parameter debug=<y/n> (default 'n') adds error msg if not a location |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _location(); |
|||
------------------------------------------------------------------------------- |
|||
p.location = function(frame) |
p.location = function(frame) |
||
local debug = (frame.args.debug or ""):sub(1, 1):lower() |
local debug = (frame.args.debug or ""):sub(1, 1):lower() |
||
| Line 2,810: | Line 1,956: | ||
end |
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) |
|||
-- {{#if:{{#invoke:PornBaseDataIB |checkBlacklist |name=Joe |suppressfields=Dave; Joe; Fred}} | not blacklisted | blacklisted}} |
|||
-- displays "blacklisted" |
|||
-- {{#if:{{#invoke:PornBaseDataIB |checkBlacklist |name=Jim |suppressfields=Dave; Joe; Fred}} | not blacklisted | blacklisted}} |
|||
-- displays "not blacklisted" |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.checkBlacklist = function(frame) |
p.checkBlacklist = function(frame) |
||
local blacklist = frame.args.suppressfields or frame.args.spf or "" |
local blacklist = frame.args.suppressfields or frame.args.spf or "" |
||
| Line 2,832: | Line 1,966: | ||
end |
end |
||
else |
else |
||
-- one of the fields is missing: let's call that "not on the list" |
|||
return true |
return true |
||
end |
end |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- emptyor returns nil if its first unnamed argument is just punctuation, whitespace or html tags |
|||
-- otherwise it returns the argument unchanged (including leading/trailing space). |
|||
-- If the argument may contain "=", then it must be called explicitly: |
|||
-- |1=arg |
|||
-- (In that case, leading and trailing spaces are trimmed) |
|||
-- It finds use in infoboxes where it can replace tests like: |
|||
-- {{#if: {{#invoke:PornBaseDataIB |getvalue |P99 |fpbd=ALL}} | <span class="xxx">{{#invoke:WikidatIB |getvalue |P99 |fpbd=ALL}}</span> | }} |
|||
-- with a form that uses just a single call to PornBaseData: |
|||
-- {{#invoke |PornBaseDataIB |emptyor |1= <span class="xxx">{{#invoke:PornBaseDataIB |getvalue |P99 |fpbd=ALL}}</span> }} |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.emptyor = function(frame) |
p.emptyor = function(frame) |
||
local s = frame.args[1] or "" |
local s = frame.args[1] or "" |
||
| Line 2,862: | Line 1,981: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- labelorid is a public function to expose the output of labelOrId() |
|||
-- Pass the Q-number as |qid= or as an unnamed parameter. |
|||
-- It returns the PornBaseData label for that entity or the qid if no label exists. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: labelOrId |
|||
------------------------------------------------------------------------------- |
|||
p.labelorid = function(frame) |
p.labelorid = function(frame) |
||
return (labelOrId(frame.args.qid or frame.args[1])) |
return (labelOrId(frame.args.qid or frame.args[1])) |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- 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) |
p.getLang = function(frame) |
||
local style = (frame.args.style or ""):lower() |
local style = (frame.args.style or ""):lower() |
||
| Line 2,890: | Line 1,994: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getItemLangCode takes a qid parameter (using the current page's qid if blank) |
|||
-- If the item for that qid has property country (P17) it looks at the first preferred value |
|||
-- If the country has an official language (P37), it looks at the first preferred value |
|||
-- If that official language has a language code (P424), it returns the first preferred value |
|||
-- Otherwise it returns nothing. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: _getItemLangCode() |
|||
------------------------------------------------------------------------------- |
|||
p.getItemLangCode = function(frame) |
p.getItemLangCode = function(frame) |
||
return _getItemLangCode(frame.args.qid or frame.args[1]) |
return _getItemLangCode(frame.args.qid or frame.args[1]) |
||
end |
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) |
p.findLanguage = function(frame) |
||
return findLang(frame.args.lang or frame.args[1]).code |
return findLang(frame.args.lang or frame.args[1]).code |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getQid returns the qid, if supplied |
|||
-- failing that, the PornBaseData entity ID of the "category's main topic (P50)", if it exists |
|||
-- failing that, the PornBaseData entity ID associated with the current page, if it exists |
|||
-- otherwise, nothing |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.getQid = function(frame) |
p.getQid = function(frame) |
||
local qid = (frame.args.qid or ""):upper() |
local qid = (frame.args.qid or ""):upper() |
||
-- check if a qid was passed; if so, return it: |
|||
if qid ~= "" then return qid end |
if qid ~= "" then return qid end |
||
-- check if there's a "category's main topic (P521)": |
|||
qid = mw.wikibase.getEntityIdForCurrentPage() |
qid = mw.wikibase.getEntityIdForCurrentPage() |
||
if qid then |
if qid then |
||
| Line 2,940: | Line 2,013: | ||
end |
end |
||
end |
end |
||
-- otherwise return the page qid (if any) |
|||
return qid |
return qid |
||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- followQid takes three optional parameters: qid, props, and all. |
|||
-- 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 PornBaseData 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, unless |all=y when all of the qids are returned, sparated by spaces. |
|||
-- If props is not given, the qid is returned. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam() |
|||
------------------------------------------------------------------------------- |
|||
p._followQid = function(args) |
p._followQid = function(args) |
||
local qid = (args.qid or ""):upper() |
local qid = (args.qid or ""):upper() |
||
| Line 2,967: | Line 2,026: | ||
local props = (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 |
for p in mw.text.gsplit(props, "%p") do |
||
p = mw.text.trim(p) |
p = mw.text.trim(p) |
||
for i, v in ipairs( mw.wikibase.getBestStatements(qid, p) ) do |
for i, v in ipairs( mw.wikibase.getBestStatements(qid, p) ) do |
||
| Line 2,976: | Line 2,035: | ||
else |
else |
||
return linkedid |
return linkedid |
||
end |
|||
end -- test for all or just the first one found |
|||
end |
|||
end -- test for value exists for that property |
|||
end |
|||
end -- loop through values of property to follow |
|||
end |
|||
end -- loop through list of properties to follow |
|||
end |
end |
||
if #out > 0 then |
if #out > 0 then |
||
| Line 2,992: | Line 2,051: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- globalSiteID returns the globalSiteID for the current wiki |
|||
-- e.g. returns "enwiki" for the English Wikipedia, "enwikisource" for English Wikisource, etc. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.globalSiteID = function(frame) |
p.globalSiteID = function(frame) |
||
return mw.wikibase.getGlobalSiteId() |
return mw.wikibase.getGlobalSiteId() |
||
end |
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) |
p.siteID = function(frame) |
||
local txtlang = frame:preprocess( "{{int:lang}}" ) or "" |
local txtlang = frame:preprocess( "{{int:lang}}" ) or "" |
||
-- This deals with specific exceptions: be-tarask -> be-x-old |
|||
if txtlang == "be-tarask" then |
if txtlang == "be-tarask" then |
||
return "be_x_old" |
return "be_x_old" |
||
| Line 3,027: | Line 2,070: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- projID returns the code used to link to the reader's language's project |
|||
-- e.g "en" for [[:en:PornBaseDataIB]] |
|||
-- treats "en-gb" as "en", etc. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.projID = function(frame) |
p.projID = function(frame) |
||
local txtlang = frame:preprocess( "{{int:lang}}" ) or "" |
local txtlang = frame:preprocess( "{{int:lang}}" ) or "" |
||
-- This deals with specific exceptions: be-tarask -> be-x-old |
|||
if txtlang == "be-tarask" then |
if txtlang == "be-tarask" then |
||
return "be-x-old" |
return "be-x-old" |
||
| Line 3,051: | Line 2,085: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- formatNumber formats a number according to the the supplied language code ("|lang=") |
|||
-- or the default language if not supplied. |
|||
-- The number is the first unnamed parameter or "|num=" |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: findLang() |
|||
------------------------------------------------------------------------------- |
|||
p.formatNumber = function(frame) |
p.formatNumber = function(frame) |
||
local lang |
local lang |
||
| Line 3,066: | Line 2,092: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- 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:PornBaseDataIB |examine |pid=P26 |qid=Q42}} |
|||
-- or {{#invoke:PornBaseDataIB |examine |P26 |Q42}} or any combination of these |
|||
-- or {{#invoke:PornBaseDataIB |examine |P26}} for the current page. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.examine = function( frame ) |
p.examine = function( frame ) |
||
local args |
local args |
||
| Line 3,100: | Line 2,115: | ||
end |
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 PornBaseData 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 P1 (instance of) is assumed. |
|||
-- It returns val if found or nothing if not found. |
|||
-- e.g. {{#invoke:PornBaseDataIB |checkvalue |val=Q5 |pid=P1 |qid=Q42}} |
|||
-- or {{#invoke:PornBaseDataIB |checkvalue |val=Q5 |P1 |qid=Q42}} |
|||
-- or {{#invoke:PornBaseDataIB |checkvalue |val=Q5 |qid=Q42}} |
|||
-- or {{#invoke:PornBaseDataIB |checkvalue |val=Q5 |P1}} for the current page. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.checkvalue = function( frame ) |
p.checkvalue = function( frame ) |
||
local args |
local args |
||
| Line 3,148: | Line 2,148: | ||
end |
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 PornBaseData" pen icon out of the microformat. |
|||
-- Usually it will take its url parameter directly from a PornBaseData call: |
|||
-- e.g. {{#invoke:PornBaseDataIB |url2 |url={{wdib |P856 |qid=Q23317 |fpbd=ALL |osd=no}} }} |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.url2 = function(frame) |
p.url2 = function(frame) |
||
local txt = frame.args.url or "" |
local txt = frame.args.url or "" |
||
| Line 3,168: | Line 2,157: | ||
prot = prot or url |
prot = prot or url |
||
addr = addr or "" |
addr = addr or "" |
||
-- strip trailing / from end of domain-only url and add <wbr/> before . and / |
|||
local disp, n = addr:gsub( "^([^/]+)/$", "%1" ):gsub("%/", "<wbr/>/"):gsub("%.", "<wbr/>.") |
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 |
||
------------------------------------------------------------------------------- |
|||
-- 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 PornBaseData" pen icon beyond the microformat if enabled. |
|||
-- A local value will override the PornBaseData value. "NONE" returns nothing. |
|||
-- e.g. {{#invoke:PornBaseDataIB |getWebsite |qid= |noicon= |lang= |url= }} |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: findLang(); parseParam(); |
|||
------------------------------------------------------------------------------- |
|||
p.getWebsite = function(frame) |
p.getWebsite = function(frame) |
||
local url = frame.args.url or "" |
local url = frame.args.url or "" |
||
| Line 3,199: | Line 2,177: | ||
urls[#urls+1] = v.mainsnak.datavalue.value |
urls[#urls+1] = v.mainsnak.datavalue.value |
||
if v.qualifiers and v.qualifiers["P208"] then |
if v.qualifiers and v.qualifiers["P208"] then |
||
-- just take the first archive url (P208) |
|||
local au = v.qualifiers["P208"][1] |
local au = v.qualifiers["P208"][1] |
||
if au.snaktype == "value" then |
if au.snaktype == "value" then |
||
quals[#urls] = au.datavalue.value |
quals[#urls] = au.datavalue.value |
||
end |
|||
end -- test for archive url having a value |
|||
end |
end |
||
end |
|||
end -- test for website having a value |
|||
end |
|||
end -- loop through website(s) |
|||
else |
else |
||
urls[1] = url |
urls[1] = url |
||
| Line 3,237: | Line 2,214: | ||
end |
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) |
p.getAllLabels = function(frame) |
||
local args = frame.args or frame:getParent().args or {} |
local args = frame.args or frame:getParent().args or {} |
||
| Line 3,264: | Line 2,234: | ||
end |
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) |
p.getAllDescriptions = function(frame) |
||
local args = frame.args or frame:getParent().args or {} |
local args = frame.args or frame:getParent().args or {} |
||
| Line 3,291: | Line 2,254: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getAllAliases fetches the set of aliases 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) |
p.getAllAliases = function(frame) |
||
local args = frame.args or frame:getParent().args or {} |
local args = frame.args or frame:getParent().args or {} |
||
| Line 3,323: | Line 2,279: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- showNoLinks displays the article titles that should not be linked. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
p.showNoLinks = function(frame) |
p.showNoLinks = function(frame) |
||
local out = {} |
local out = {} |
||
| Line 3,338: | Line 2,288: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- checkValidity checks whether the first unnamed parameter represents a valid entity-id, |
|||
-- that is, something like Q1235 or P123. |
|||
-- It returns the strings "true" or "false". |
|||
-- Change false to nil to return "true" or "" (easier to test with #if:). |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: none |
|||
------------------------------------------------------------------------------- |
|||
function p.checkValidity(frame) |
function p.checkValidity(frame) |
||
local id = mw.text.trim(frame.args[1] or "") |
local id = mw.text.trim(frame.args[1] or "") |
||
| Line 3,356: | Line 2,297: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getEntityFromTitle returns the Entity-ID (Q-number) for a given title. |
|||
-- Modification of Module:ResolveEntityId |
|||
-- The title is the first unnamed parameter. |
|||
-- The site parameter determines the site/language for the title. Defaults to current wiki. |
|||
-- The showdab parameter determines whether dab pages should return the Q-number or nil. Defaults to true. |
|||
-- Returns the Q-number or nil if it does not exist. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam |
|||
------------------------------------------------------------------------------- |
|||
function p.getEntityFromTitle(frame) |
function p.getEntityFromTitle(frame) |
||
local args=frame.args |
local args=frame.args |
||
| Line 3,385: | Line 2,315: | ||
end |
end |
||
------------------------------------------------------------------------------- |
|||
-- getDatePrecision returns the number representing the precision of the first best date value |
|||
-- for the given property. |
|||
-- It takes the qid and property ID |
|||
-- 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 |
|||
-- Returns 0 (or the second unnamed parameter) if the PornBaseData does not exist. |
|||
------------------------------------------------------------------------------- |
|||
-- Dependencies: parseParam; sourced; |
|||
------------------------------------------------------------------------------- |
|||
function p.getDatePrecision(frame) |
function p.getDatePrecision(frame) |
||
local args=frame.args |
local args=frame.args |
||
| Line 3,419: | Line 2,338: | ||
return p |
return p |
||
------------------------------------------------------------------------------- |
|||
-- List of exported functions |
|||
------------------------------------------------------------------------------- |
|||
--[[ |
|||
_getValue |
|||
getValue |
|||
getPreferredValue |
|||
getCoords |
|||
getQualifierValue |
|||
getSumOfParts |
|||
getValueByQual |
|||
getValueByLang |
|||
getValueByRefSource |
|||
getPropertyIDs |
|||
getQualifierIDs |
|||
getPropOfProp |
|||
getAwardCat |
|||
getIntersectCat |
|||
getGlobe |
|||
getCommonsLink |
|||
getSiteLink |
|||
getLink |
|||
getLabel |
|||
label |
|||
getAT |
|||
getDescription |
|||
getAliases |
|||
pageId |
|||
formatDate |
|||
location |
|||
checkBlacklist |
|||
emptyor |
|||
labelorid |
|||
getLang |
|||
getItemLangCode |
|||
findLanguage |
|||
getQID |
|||
followQid |
|||
globalSiteID |
|||
siteID |
|||
projID |
|||
formatNumber |
|||
examine |
|||
checkvalue |
|||
url2 |
|||
getWebsite |
|||
getAllLabels |
|||
getAllDescriptions |
|||
getAllAliases |
|||
showNoLinks |
|||
checkValidity |
|||
getEntityFromTitle |
|||
getDatePrecision |
|||
--]] |
|||
------------------------------------------------------------------------------- |
|||
Latest revision as of 02:22, 14 January 2025
Documentation for this module may be created at Module:PornBaseDataIB/doc
local p = {}
local cdate
local dp = {
[6] = "millennium",
[7] = "century",
[8] = "decade",
[9] = "year",
[10] = "month",
[11] = "day",
}
local i18n =
{
["errors"] =
{
["property-not-found"] = "Property not found.",
["No property supplied"] = "No property supplied",
["entity-not-found"] = "PornBaseData entity not found.",
["unknown-claim-type"] = "Unknown claim type.",
["unknown-entity-type"] = "Unknown entity type.",
["qualifier-not-found"] = "Qualifier not found.",
["site-not-found"] = "Pornographic Central 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 PornBaseData, but not on PBC",
["dab-page"] = " (dab)",
},
["months"] =
{
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
},
["century"] = "century",
["BC"] = "BC",
["BCE"] = "BCE",
["ordinal"] =
{
[1] = "st",
[2] = "nd",
[3] = "rd",
["default"] = "th"
},
["filespace"] = "File",
["Unknown"] = "Unknown",
["NaN"] = "Not a number",
["missinginfocat"] = "[[Category:Articles with missing PornBaseData information]]",
["editonpornbasedata"] = "Edit this on PornBaseData",
["latestdatequalifier"] = function (date) return "before " .. date end,
["datenumbersuffix"] = "",
["list separator"] = ", ",
["multipliers"] = {
[0] = "",
[3] = " thousand",
[6] = " million",
[9] = " billion",
[12] = " trillion",
}
}
if 'en' ~= mw.getContentLanguage():getCode() then
require("Module:i18n").loadI18n("Module:PornBaseDataIB/i18n", i18n)
end
local collapsediv = '<div class="mw-collapsible mw-collapsed" style="width:100%; overflow:auto;" data-expandtext="{{int:show}}" data-collapsetext="{{int:hide}}">'
local donotlink = {}
local nolinks_exists, nolinks = pcall(mw.loadData, "Module:PornBaseDataIB/nolinks")
if nolinks_exists then
donotlink = nolinks.itemsindex
end
local formats = {}
local titleformats_exists, titleformats = pcall(mw.loadData, "Module:PornBaseDataIB/titleformats")
if titleformats_exists then
formats = titleformats.formats
end
local makeOrdinal = function(cardinal)
local ordsuffix = i18n.ordinal.default
if cardinal % 10 == 1 then
ordsuffix = i18n.ordinal[1]
elseif cardinal % 10 == 2 then
ordsuffix = i18n.ordinal[2]
elseif cardinal % 10 == 3 then
ordsuffix = i18n.ordinal[3]
end
if (cardinal % 100 == 11) or (cardinal % 100 == 12) or (cardinal % 100 == 13) then
ordsuffix = i18n.ordinal.default
end
return tostring(cardinal) .. ordsuffix
end
local findLang = function(langcode)
local langobj
langcode = mw.text.trim(langcode or "")
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
end
local _getItemLangCode = function(qid)
qid = mw.text.trim(qid or ""):upper()
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return end
local prop40 = mw.wikibase.getBestStatements(qid, "P40")[1]
if not prop40 or prop40.mainsnak.snaktype ~= "value" then return end
local qid40 = prop40.mainsnak.datavalue.value.id
local prop256 = mw.wikibase.getBestStatements(qid256, "P256")[1]
if not prop256 or prop256.mainsnak.snaktype ~= "value" then return end
local qid256 = prop256.mainsnak.datavalue.value.id
local prop329 = mw.wikibase.getBestStatements(qid256, "P329")[1]
if not prop329 or prop329.mainsnak.snaktype ~= "value" then return end
return prop329.mainsnak.datavalue.value
end
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 p = 10 ^ (math.floor(math.log10(x)) - sf + 1)
x = math.floor(x / p + 0.5) * p * s
if x == math.floor(x) then x = math.floor(x) end
return x
end
local decimalToDMS = function(x, p)
if not tonumber(p) then p = 1e-4 end
local d = math.floor(x)
local ms = (x - d) * 60
if p > 0.5 then
if ms > 30 then d = d + 1 end
ms = 0
end
local m = math.floor(ms)
local s = (ms - m) * 60
if p > 0.008 then
if s > 30 then m = m +1 end
s = 0
elseif p > 0.00014 then
s = math.floor(s + 0.5)
elseif p > 0.000014 then
s = math.floor(10 * s + 0.5) / 10
elseif p > 0.0000014 then
s = math.floor(100 * s + 0.5) / 100
else
s = math.floor(1000 * s + 0.5) / 1000
end
return d, m, s
end
local decimalPrecision = function(x, p)
local s = 1
if x < 0 then
x = -x
s = -1
end
if not tonumber(p) then p = 1e-4
elseif p > 1 then p = 1
elseif p < 1e-6 then p = 1e-6
else p = 10 ^ math.floor(math.log10(p))
end
x = math.floor(x / p + 0.5) * p * s
if x == math.floor(x) then x = math.floor(x) end
if math.abs(x) < 1e-4 then x = string.format("%f", x) end
return x
end
local format_Date = function(datetime, dateformat, bc)
local datetime = datetime or "1 August 30 BCE"
local dateval = string.match( datetime, "[%w ]+")
local dateformat = string.lower(dateformat or "dmy")
local bc = string.upper(bc or "")
if bc == "BC" then
bc = " " .. i18n["BC"]
else
bc = " " .. i18n["BCE"]
end
local postchrist = true
local dateparts = {}
for word in string.gmatch(dateval, "%w+") do
if word == "BCE" or word == "BC" then
postchrist = false
else
dateparts[#dateparts + 1] = word
end
end
if postchrist then bc = "" end
local sep = " "
local fdate = table.concat(dateparts, sep)
if #dateparts == 3 then
if dateformat == "y" then
fdate = dateparts[3]
elseif dateformat == "mdy" then
fdate = dateparts[2] .. sep .. dateparts[1] .. "," .. sep .. dateparts[3]
end
elseif #dateparts == 2 and dateformat == "y" then
fdate = dateparts[2]
end
return fdate .. bc
end
local dateFormat = function(timestamp, dprec, df, bcf, pd, qualifiers, lang, adj, model)
df = (df or ""):lower()
if df == "ymd" then
if timestamp:sub(1,1) == "+" then
return timestamp:sub(2,11)
else
local yr = tonumber(timestamp:sub(2,5)) - 1
yr = ("000" .. yr):sub(-4)
if yr ~= "0000" then yr = "-" .. yr end
return yr .. timestamp:sub(6,11)
end
end
timestamp = timestamp:gsub("%-00%-00T", "-01-01T")
dprec = dprec or 11
if df == "y" and dprec > 9 then dprec = 9 end
dprec = dprec>11 and 11 or dprec
dprec = dprec<6 and 6 or dprec
bcf = (bcf or ""):upper()
pd = (pd or ""):sub(1,1):lower()
if pd == "" or pd == "n" or pd == "f" or pd == "0" then pd = false end
lang = lang or findLang().code
adj = adj or ""
local bc = timestamp:sub(1, 1)=="-" and "BC" or ""
local year, month, day = timestamp:match("[+-](%d*)-(%d*)-(%d*)T")
local iso = tonumber(year)
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
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 calendarmodel = ""
if tonumber(year) > 1582
and dprec > 8
and not pd
and model == "https://pornbasedata.com/wiki/Q219" then
calendarmodel = "julian"
end
if not cdate then
cdate = require("Module:Complex date")._complex_date
end
local fdate = cdate(calendarmodel, adj, tostring(iso), dp[dprec], bc, "", "", "", "", lang, 1)
fdate = fdate:gsub(' <div style="display: none;">[^<]*</div>', '')
fdate = fdate:gsub("<[^>]*>", "")
fdate = fdate:gsub("^0*", "")
if pd then
fdate = fdate:gsub("%[%[.*|", ""):gsub("]]", "")
end
fdate = fdate:gsub('circa ', '<abbr title="circa">c.</abbr> ')
if bcf == "BCE" then
fdate = fdate:gsub('BC', 'BCE')
end
if df == "mdy" then
fdate = fdate:gsub("(%d+) (%w+) (%d+)", "%2 %1, %3")
end
if pd == "a" then
fdate = fdate:gsub(' century', '-century')
end
return fdate
end
local parseParam = function(param, default)
if type(param) == "boolean" then param = tostring(param) end
if param and param ~= "" then
param = param:lower()
if (param == "false") or (param:sub(1,1) == "n") or (param == "0") then
return false
else
return true
end
else
return default
end
end
local _getSitelink = function(qid, wiki)
qid = (qid or ""):upper()
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return nil end
wiki = wiki or ""
local sitelink
if wiki == "" then
sitelink = mw.wikibase.getSitelink(qid)
else
sitelink = mw.wikibase.getSitelink(qid, wiki)
end
return sitelink
end
local _getCommonslink = function(qid, onlycat, fallback)
qid = (qid or ""):upper()
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return nil end
onlycat = parseParam(onlycat, false)
if fallback == "" then fallback = nil end
local sitelink = _getSitelink(qid, "pbcimagerepo")
if onlycat and sitelink and sitelink:sub(1,9) ~= "Category:" then sitelink = nil end
if not sitelink then
local prop50 = mw.wikibase.getBestStatements(qid, "P50")[1]
if prop50 then
local tmcid = prop50.mainsnak.datavalue and prop50.mainsnak.datavalue.value.id
sitelink = _getSitelink(tmcid, "pbcimagerepo")
end
if not sitelink then
local prop189 = mw.wikibase.getBestStatements(qid, "P189")[1]
if prop189 then
local tmcid = prop189.mainsnak.datavalue and prop189.mainsnak.datavalue.value.id
sitelink = _getSitelink(tmcid, "pbcimagerepo")
end
end
end
if not sitelink and fallback then
local prop191 = mw.wikibase.getBestStatements(qid, "P191")[1]
if prop191 then
sitelink = prop191.mainsnak.datavalue and prop191.mainsnak.datavalue.value
if sitelink then sitelink = "Category:" .. sitelink end
end
end
return sitelink
end
local labelOrId = function(id, lang)
if lang == "default" then lang = findLang().code end
local label
if lang then
label = mw.wikibase.getLabelByLang(id, lang)
else
label = mw.wikibase.getLabel(id)
end
if label then
return mw.text.nowiki(label), true
else
return id, false
end
end
local linkedItem = function(id, lprefix, lpostfix, prefix, postfix, dtxt, shortname, lang, uselbl)
lprefix = lprefix or ""
lpostfix = lpostfix or ""
prefix = prefix or ""
postfix = postfix or ""
lang = lang or "pbc"
local fmt = ""
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P1") ) do
if v.mainsnak.datavalue and formats[v.mainsnak.datavalue.value.id] then
fmt = formats[v.mainsnak.datavalue.value.id]
break
end
end
local disp
local sitelink = mw.wikibase.getSitelink(id)
local label, islabel
if dtxt then
label, islabel = dtxt, true
elseif shortname then
for k, v in ipairs( mw.wikibase.getBestStatements(id, "P203") ) do
if v.mainsnak.datavalue.value.language == lang then
label, islabel = v.mainsnak.datavalue.value.text, true
break
end
end
if not islabel then
label, islabel = labelOrId(id)
shortname = false
end
else
label, islabel = labelOrId(id)
end
if mw.site.siteName ~= "PBC Image Repository" then
if sitelink then
if not (dtxt or shortname) then
if sitelink:lower() ~= label:lower() then
local pos = sitelink:find(":") or 0
local slink = sitelink
if pos > 0 then
local prefix = sitelink:sub(1,pos-1)
if mw.site.namespaces[prefix] then
slink = sitelink:sub(pos+1)
end
end
slink = slink:gsub("%s%(.+%)$", ""):gsub(",.+$", "")
if not uselbl then
if label:find("^%u") then
label = slink:gsub("^(%l)", string.upper)
else
label = slink:gsub("^(%u)", string.lower)
end
end
end
end
if donotlink[label] then
disp = prefix .. fmt .. label .. fmt .. postfix
else
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]"
end
elseif islabel then
local artitle = mw.title.new(label, 0)
if not donotlink[label] and artitle and artitle.redirectTarget then
disp = "[[".. lprefix .. label .. lpostfix .. "|" .. prefix .. fmt .. label .. fmt .. postfix .. "]]"
else
disp = prefix .. fmt .. label .. fmt .. postfix
end
else
if mw.wikibase.getGlobalSiteId() == "pbcimagerepo" then
disp = i18n.missinginfocat
else
disp = prefix .. label .. postfix .. i18n.missinginfocat
end
end
else
local ccat = mw.wikibase.getBestStatements(id, "P191")[1]
if ccat and ccat.mainsnak.datavalue then
ccat = ccat.mainsnak.datavalue.value
disp = "[[" .. lprefix .. "Category:" .. ccat .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
elseif sitelink then
disp = "[[" .. lprefix .. sitelink .. lpostfix .. "|" .. prefix .. label .. postfix .. "]]"
else
disp = prefix .. label .. postfix
end
end
return disp
end
local sourced = function(claim)
if claim.references then
for kr, vr in pairs(claim.references) do
local ref = mw.wikibase.renderSnaks(vr.snaks)
if not ref:find("Wiki") then
return true
end
end
end
end
local setRanks = function(rank)
rank = (rank or ""):lower()
local ranks = {}
for w in string.gmatch(rank, "%a+") do
w = w:sub(1,1)
if w == "b" or w == "p" or w == "n" or w == "d" then
ranks[w] = true
end
end
if ranks.b or not next(ranks) then
ranks.p = true
ranks.n = true
end
return ranks
end
local parseInput = function(frame, input_parm, property_id)
input_parm = mw.text.trim(input_parm or "")
if input_parm == "" then input_parm = nil end
if not mw.wikibase then return false, input_parm end
local args = frame.args
local qid = args.qid or ""
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return false, input_parm end
local blacklist = args.suppressfields or args.spf or ""
local whitelist = args.fetchpornbasedata or args.fpbd or ""
if whitelist == "" then whitelist = "NONE" end
local fieldname = args.name or ""
if blacklist ~= "" then
if fieldname == "" then return false, nil end
if blacklist:find(fieldname) then return false, nil end
end
if input_parm then return false, input_parm end
if property_id:sub(1,1):upper() ~="P" or property_id == "P0" then return false, nil end
local _, found = whitelist:find(fieldname)
found = ((found or 0) > 0)
if whitelist ~= 'ALL' and (whitelist:upper() == "NONE" or not found) then
return false, nil
end
local props = {}
if args.reqranks.b then
props = mw.wikibase.getBestStatements(qid, property_id)
else
props = mw.wikibase.getAllStatements(qid, property_id)
end
if props[1] then
return qid, props
end
return false, nil
end
local createicon = function(langcode, entityID, propertyID)
local icon = " <span class='penicon'>[["
.. i18n["filespace"]
.. ":OOjs UI icon edit-ltr-progressive.svg |frameless |text-top |10px |alt="
.. i18n["editonpornbasedata"]
.. "|link=https://pornbasedata.com/wiki/" .. entityID
.. "?uselang=" .. langcode
if propertyID then icon = icon .. "#" .. propertyID end
icon = icon .. "|" .. i18n["editonpornbasedata"] .. "]]</span>"
return icon
end
local assembleoutput = function(out, args, entityID, propertyID)
local sorted = parseParam(args.sorted, false)
local noic = parseParam(args.noicon, false)
local list = args.list or ""
local sepdefault = i18n["list separator"]
local separator = args.sep or ""
separator = string.gsub(separator, '"', '')
if separator == "" then
separator = sepdefault
end
local collapse = tonumber(args.collapse) or 0
local replacetext = mw.text.trim(args.rt or args.replacetext or "")
local strout
if #out > 0 then
if sorted then table.sort(out) end
local hasdisplay = false
for i, v in ipairs(out) do
if v ~= i18n.missinginfocat then
hasdisplay = true
break
end
end
if not noic and hasdisplay then
out[#out] = out[#out] .. createicon(args.langobj.code, entityID, propertyID)
end
if list == "" then
strout = table.concat(out, separator)
elseif list:lower() == "prose" then
strout = mw.text.listToText( out )
else
strout = mw.getCurrentFrame():expandTemplate{title = list, args = out}
end
if collapse >0 and #out > collapse then
strout = collapsediv .. strout .. "</div>"
end
else
strout = nil
end
if replacetext ~= "" and strout then strout = replacetext end
return strout
end
local rendersnak = function(propval, args, linked, lpre, lpost, pre, post, uabbr, filter)
lpre = lpre or ""
lpost = lpost or ""
pre = pre or ""
post = post or ""
args.lang = args.lang or findLang().code
local dtxt = args.displaytext or args.dt
if dtxt == "" then dtxt = nil end
local shortname = args.shortname or args.sn
shortname = parseParam(shortname, false)
local uselbl = args.uselabel or args.uselbl
uselbl = parseParam(uselbl, false)
local snak = propval.mainsnak or propval
local dtype = snak.datatype
local dv = snak.datavalue
dv = dv and dv.value
local val, mlt
if propval.rank and not args.reqranks[propval.rank:sub(1, 1)] then
elseif snak.snaktype == "somevalue" then
val = i18n["Unknown"]
elseif snak.snaktype == "novalue" then
elseif dtype == "wikibase-item" then
local qnumber = dv.id
if linked then
val = linkedItem(qnumber, lpre, lpost, pre, post, dtxt, shortname, args.lang, uselbl)
else
local label, islabel
if dtxt then
label = dtxt
else
label, islabel = labelOrId(qnumber)
local langlabel = mw.wikibase.getLabelByLang(qnumber, args.lang)
if langlabel then
label = mw.text.nowiki( langlabel )
end
end
val = pre .. label .. post
end
elseif dtype == "time" then
val = dateFormat(dv.time, dv.precision, args.df, args.bc, args.pd, propval.qualifiers, args.lang, "", dv.calendarmodel)
elseif dtype == "localMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then
if (lpre == "" or lpre == ":") and lpost == "" then
val = pre .. dv .. post
elseif dtype == "external-id" then
val = "[" .. lpre .. dv .. lpost .. " " .. pre .. dv .. post .. "]"
else
val = "[[" .. lpre .. dv .. lpost .. "|" .. pre .. dv .. post .. "]]"
end
elseif dtype == "quantity" then
local fnum = true
local conv = parseParam(args.conv or args.convert, false)
if conv then
uabbr = true
fnum = false
args.scale = "0"
end
local showunits = parseParam(args.su or args.showunits, true)
local amount = tonumber(dv.amount) or i18n["NaN"]
local sc = tostring(args.scale or ""):sub(1,1):lower()
local scale
if sc == "a" then
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
local range = ""
local upb = tonumber(dv.upperBound)
local lowb = tonumber(dv.lowerBound)
if upb and lowb then
local posdif = roundto(upb - amount, 2) / factor
local negdif = roundto(amount - lowb, 2) / factor
upb, lowb = amount + posdif, amount - negdif
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
range = " +" .. posdif .. " -" .. negdif
elseif posdif ~= 0 then
range = " ±" .. posdif
else
end
else
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
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 and showunits then
local uname = mw.wikibase.getLabelByLang(unitqid, args.lang) or ""
if uname ~= "" then usep, unit = " ", uname end
if uabbr then
local unitsymbols = mw.wikibase.getBestStatements(unitqid, "P5061")
local fbtbl = mw.language.getFallbacksFor( args.lang )
table.insert( fbtbl, 1, args.lang )
table.insert( fbtbl, 1, "mul" )
local 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
end
if found then usep, unit = " ", usym end
end
end
if conv then
if range == "" then
val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {amount, unit}}
else
val = mw.getCurrentFrame():expandTemplate{title = "cvt", args = {lowb, "to", upb, unit}}
end
elseif unit == "$" or unit == "£" then
val = unit .. amount .. range .. i18n.multipliers[scale]
else
val = amount .. range .. i18n.multipliers[scale] .. usep .. unit
end
elseif dtype == "globe-coordinate" then
local form = (args.format or ""):lower():sub(1,3)
if form ~= "dec" then form = "dms" end
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
val = pre .. dv.text .. post
mlt = dv.language
else
val = "unknown data type: " .. dtype
end
return val, mlt
end
local function propertyvalueandquals(objproperty, args, qualID)
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local linked = parseParam(args.linked, true)
local prefix = (args.prefix or ""):gsub('"', '')
local postfix = (args.postfix or ""):gsub('"', '')
local lprefix = (args.linkprefix or args.lp or ""):gsub('"', '')
local lpostfix = (args.linkpostfix or ""):gsub('"', '')
local wdl = parseParam(args.wdlinks or args.wdl, false)
local uabbr = parseParam(args.unitabbr or args.uabbr, false)
local qualsonly = parseParam(args.qualsonly or args.qo, false)
local maxvals = tonumber(args.maxvals) or 0
local pd = args.plaindate or args.pd or "no"
args.pd = pd
args.qdf = args.qdf or args.qualifierdateformat or args.df or "y"
local lang = args.lang or findlang().code
qualID = qualID or ""
qualID = qualID:upper():gsub("DATES", "P580, P582")
local allflag = (qualID == "ALL")
local qwanted = {}
local qorder = {}
for q in mw.text.gsplit(qualID, "%p") do
local qtrim = mw.text.trim(q)
if qtrim ~= "" then
qwanted[mw.text.trim(q)] = true
qorder[#qorder+1] = qtrim
end
end
local qsep = (args.qsep or ""):gsub('"', '')
local qargs = {
["osd"] = "false",
["linked"] = tostring(linked),
["prefix"] = args.qprefix,
["postfix"] = args.qpostfix,
["linkprefix"] = args.qlinkprefix or args.qlp,
["linkpostfix"] = args.qlinkpostfix,
["wdl"] = "false",
["unitabbr"] = tostring(uabbr),
["maxvals"] = 0,
["sorted"] = tostring(args.qsorted),
["noicon"] = "true",
["list"] = args.qlist,
["sep"] = qsep,
["langobj"] = args.langobj,
["lang"] = args.langobj.code,
["df"] = args.qdf,
["sn"] = parseParam(args.qsn or args.qshortname, false),
}
local datatype = objproperty[1].datatype or objproperty[1].mainsnak.datatype
local out = {}
local mlt = {}
for k, v in ipairs(objproperty) do
local hasvalue = true
if (onlysrc and not sourced(v)) then
hasvalue = false
else
local val, lcode = rendersnak(v, args, linked, lprefix, lpostfix, prefix, postfix, uabbr)
if not val then
hasvalue = false
elseif qualsonly and qualID then
else
out[#out+1], mlt[#out+1] = val, lcode
end
end
local snak = v.mainsnak or v
if hasvalue and v.qualifiers and qualID ~= "" and snak.snaktype~="novalue" then
local qlist = {}
local timestart, timeend = "", ""
for k1, v1 in pairs(v.qualifiers) do
if allflag or qwanted[k1] then
if k1 == "P194" then
local ts = v1[1].datavalue.value.time
local dp = v1[1].datavalue.value.precision
qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "before")
elseif k1 == "P198" then
local ts = v1[1].datavalue.value.time
local dp = v1[1].datavalue.value.precision
qlist[k1] = dateFormat(ts, dp, args.qdf, args.bc, pd, "", lang, "after")
elseif k1 == "P34" then
timestart = propertyvalueandquals(v1, qargs)[1] or ""
elseif k1 == "P41" then
timeend = propertyvalueandquals(v1, qargs)[1] or ""
else
local q = assembleoutput(propertyvalueandquals(v1, qargs), qargs)
if datatype ~= "time" or q ~= "circa" and not (type(q) == "string" and q:find("circa]]")) then
qlist[k1] = q
end
end
end
end
local t = timestart .. timeend
local dsep = "–"
if t:find("%s") or t:find(" ") then dsep = " – " end
if next(qlist) then
local qlistout = {}
if allflag then
for k2, v2 in pairs(qlist) do
qlistout[#qlistout+1] = v2
end
else
for i2, v2 in ipairs(qorder) do
qlistout[#qlistout+1] = qlist[v2]
end
end
if t ~= "" then
qlistout[#qlistout+1] = timestart .. dsep .. timeend
end
local qstr = assembleoutput(qlistout, qargs)
if qualsonly then
out[#out+1] = qstr
else
out[#out] = out[#out] .. " (" .. qstr .. ")"
end
elseif t ~= "" then
if qualsonly then
out[#out+1] = timestart .. dsep .. timeend
else
out[#out] = out[#out] .. " (" .. timestart .. dsep .. timeend .. ")"
end
end
end
if maxvals > 0 and #out >= maxvals then break end
end
if datatype == "monolingualtext" and #out >1 then
lang = mw.text.split( lang, '-', true )[1]
local fbtbl = mw.language.getFallbacksFor( lang )
table.insert( fbtbl, 1, lang )
local bestval = ""
local 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
end
if found then
out = { bestval }
else
out = { out[1] }
end
end
return out
end
local _getvaluebyqual = function(frame, qualID, checkvalue)
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
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)
frame.args.reqranks = setRanks(frame.args.rank)
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
local args = frame.args
local qid, props = parseInput(frame, args[2], propertyID)
local linked = parseParam(args.linked, true)
local lpre = (args.linkprefix or args.lp or ""):gsub('"', '')
local lpost = (args.linkpostfix or ""):gsub('"', '')
local pre = (args.prefix or ""):gsub('"', '')
local post = (args.postfix or ""):gsub('"', '')
local uabbr = parseParam(args.unitabbr or args.uabbr, false)
local filter = (args.unit or ""):upper()
if filter == "" then filter = nil end
if qid then
local out = {}
for k1, v1 in ipairs(props) do
if v1.mainsnak.snaktype == "value" then
local v1q = v1.qualifiers
if v1q and v1q[qualID] then
if onlysrc == false or sourced(v1) then
if v1q[qualID][1].datatype == "wikibase-item" then
if checkvalue(v1q[qualID][1].datavalue.value.id) then
out[#out + 1] = rendersnak(v1, args, linked, lpre, lpost, pre, post, uabbr, filter)
end
elseif v1q[qualID][1].datatype == "string" then
if checkvalue(v1q[qualID][1].datavalue.value) then
out[#out + 1] = rendersnak(v1, args, linked, lpre, lpost, pre, post, uabbr, filter)
end
end
end
end
else
return nil
end
end
return assembleoutput(out, frame.args, qid, propertyID)
else
return props
end
return nil
end
local _location = function(qid, first, skip)
first = parseParam(first, false)
skip = parseParam(skip, false)
local locs = {"P196", "P49", "P202"}
local out = {}
local langcode = findLang():getCode()
local finished = false
local count = 0
local prevqid = "Q0"
repeat
local prop
for i1, v1 in ipairs(locs) do
local proptbl = mw.wikibase.getBestStatements(qid, v1)
if #proptbl > 1 then
local prevP49, prevP49id
if prevqid ~= "Q0" then
prevP49 = mw.wikibase.getBestStatements(prevqid, "P49")[1]
prevP49id = prevP49
and prevP49.mainsnak.datavalue
and prevP49.mainsnak.datavalue.value.id
end
for i2, v2 in ipairs(proptbl) do
parttbl = v2.qualifiers and v2.qualifiers.P200
if parttbl then
for i3, v3 in ipairs(parttbl) do
if v3.snaktype == "value" and v3.datavalue.value.id == prevqid then
prop = proptbl[i2]
break
end
end
else
if qid == prevP49id then
prop = proptbl[i2]
break
end
end
end
prop = prop or proptbl[2]
elseif #proptbl > 0 then
prop = proptbl[1]
end
if prop then break end
end
local inst = mw.wikibase.getAllStatements(qid, "P1")
if #inst > 0 then
for k, v in ipairs(inst) do
local instid = v.mainsnak.datavalue.value.id
if instid == "Q210" or instid == "Q1041" or (skip and instid == "Q3336843") then
prop = nil
break
end
end
end
if prop and prop.mainsnak.datavalue then
if not skip or count == 0 then
out[#out+1] = linkedItem(qid, ":", "", "", "")
end
qid, prevqid = prop.mainsnak.datavalue.value.id, qid
else
local prop203 = mw.wikibase.getAllStatements(qid, "P203")
if prop203[1] and (#out > 0)then
local shortname
for k, v in pairs(prop203) 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
if shortname ~= "USA" then
out[#out+1] = shortname or labelOrId(qid)
else
if skip then out[#out+1] = "US" end
end
else
local loc = labelOrId(qid)
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
if not first then table.remove(out, 1) end
if #out > 2 then
local plain = {}
for i, v in ipairs(out) do
plain[i] = v:gsub("^%[%[[^|]*|", ""):gsub("]]$", "")
end
local idx = 2
repeat
if plain[idx] == plain[idx-1] then
local removeidx = 0
if (plain[idx] ~= out[idx]) and (plain[idx-1] == out[idx-1]) then
removeidx = idx - 1
elseif (plain[idx] == out[idx]) and (plain[idx-1] ~= out[idx-1]) then
removeidx = idx
else
removeidx = idx - (os.time()%2)
end
table.remove(out, removeidx)
table.remove(plain, removeidx)
else
idx = idx +1
end
until idx >= #out
end
return out
end
local _getsumofparts = function(args)
local vallist = (args.vlist or ""):upper()
if vallist == "" then return end
args.reqranks = setRanks(args.rank)
local f = {}
f.args = args
local qid, props = parseInput(f, "", "P173")
if not qid then return 0 end
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local sum = 0
for k1, v1 in ipairs(props) do
if (onlysrc == false or sourced(v1))
and v1.mainsnak.snaktype == "value"
and v1.mainsnak.datavalue.type == "wikibase-entityid"
and vallist:match( v1.mainsnak.datavalue.value.id )
and v1.qualifiers
then
local quals = v1.qualifiers["P204"]
if quals then
for k2, v2 in ipairs(quals) do
sum = sum + v2.datavalue.value.amount
end
end
end
end
return sum
end
p._getValue = function(args)
local paraset = tonumber(args.ps or args.parameterset or 0)
if paraset == 1 then
args.rank = "best"
args.fetchpornbasedata = "ALL"
args.onlysourced = "no"
args.noicon = "true"
elseif paraset == 2 then
args.rank = "best"
args.fetchpornbasedata = "ALL"
args.onlysourced = "no"
args.noicon = "true"
args.linked = "no"
args.pd = "true"
elseif paraset == 3 then
end
local eid = args.eid
if eid == "" then
return nil
elseif eid then
args.qid = eid
end
local propertyID = mw.text.trim(args[1] or "")
args.reqranks = setRanks(args.rank)
local replacetext = mw.text.trim(args.rt or args.replacetext or "")
if replacetext ~= "" then
args.fetchpornbasedata = "ALL"
end
local f = {}
f.args = args
local entityid, props = parseInput(f, f.args[2], propertyID)
if not entityid then
return props
end
local qualID = mw.text.trim(args.qual or ""):upper()
if qualID == "" then qualID = nil end
args.langobj = findLang(args.lang)
args.lang = args.langobj.code
local out = propertyvalueandquals(props, args, qualID)
return assembleoutput(out, args, entityid, propertyID)
end
p.getValue = function(frame)
local args= frame.args
if not args[1] then
args = frame:getParent().args
if not args[1] then return i18n.errors["No property supplied"] end
end
return p._getValue(args)
end
p.getPreferredValue = function(frame)
frame.args.rank = "best"
return p.getValue(frame)
end
p.getCoords = function(frame)
local propertyID = "P48"
local disp = frame.args.display or ""
if disp == "" then
disp = "inline, title"
end
local form = (frame.args.format or ""):lower():sub(1,3)
if form ~= "dec" then
form = "dms"
end
frame.args.reqranks = setRanks("best")
local qid, props = parseInput(frame, frame.args[1], propertyID)
if not qid then
return props
else
local dv = props[1].mainsnak.datavalue.value
local lat, long, prec = dv.latitude, dv.longitude, dv.precision
lat = decimalPrecision(lat, prec)
long = decimalPrecision(long, prec)
local lat_long = { lat, long }
lat_long["display"] = disp
lat_long["format"] = form
return frame:expandTemplate{title = 'coord', args = lat_long}
end
end
p.getQualifierValue = function(frame)
local propertyID = mw.text.trim(frame.args[1] or "")
local propvalue = frame.args.pval
local qualifierID = frame.args.qual
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
frame.args.reqranks = setRanks(frame.args.rank)
local qid, props = parseInput(frame, frame.args[2], propertyID)
if qid then
local out = {}
for k1, v1 in pairs(props) do
if v1.mainsnak.snaktype == "value" and v1.mainsnak.datavalue.type == "wikibase-entityid" then
if v1.mainsnak.datavalue.value.id == propvalue and v1.qualifiers then
if onlysrc == false or sourced(v1) then
local quals = v1.qualifiers[qualifierID]
if quals then
local qargs = frame.args
qargs.onlysourced = "no"
local vals = propertyvalueandquals(quals, qargs, qid)
for k, v in ipairs(vals) do
out[#out + 1] = v
end
end
end
end
end
end
return assembleoutput(out, frame.args, qid, propertyID)
else
return props
end
return nil
end
p.getSumOfParts = function(frame)
local sum = _getsumofparts(frame.args)
if sum == 0 then return end
return sum
end
p.getValueByQual = function(frame)
local qualID = frame.args.qualID
local qval = frame.args.qvalue or ""
if qval == "" then return "no qualifier value supplied" end
local function checkQID(id)
return id == qval
end
return _getvaluebyqual(frame, qualID, checkQID)
end
p.getValueByLang = function(frame)
local langcode = findLang(frame.args.lang).code
local function checkLanguage(id)
local qlcode = mw.wikibase.getBestStatements(id, "P329")
if (#qlcode > 0) and (qlcode[1].mainsnak.datavalue.value == langcode) then
return true
end
end
return _getvaluebyqual(frame, "P44", checkLanguage)
end
p.getValueByRefSource = function(frame)
local propertyID = mw.text.trim(frame.args[1] or ""):upper()
if propertyID == "" then return "no property supplied" end
local qval = (frame.args.match or ""):upper()
if qval == "" then qval = "Q21540096" end
local unit = (frame.args.unit or ""):upper()
if unit == "" then unit = "Q1058" end
local onlysrc = parseParam(frame.args.onlysourced or frame.args.osd, true)
frame.args.reqranks = setRanks(frame.args.rank)
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)
local qid, props = parseInput(frame, frame.args[2], propertyID)
if qid then
local out = {}
local mlt= {}
for k1, v1 in ipairs(props) do
if onlysrc == false or sourced(v1) then
if v1.references then
for k2, v2 in ipairs(v1.references) do
if v2.snaks.P15 then
for k3, v3 in ipairs(v2.snaks.P15) do
if v3.datavalue.value.id == qval then
out[#out+1], mlt[#out+1] = rendersnak(v1, frame.args, linked, "", "", "", "", uabbr, unit)
if not mlt[#out] then
break
end
end
end
end
end
end
end
end
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 )
local bestval = ""
local 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
end
if found then
out = { bestval }
else
out = { out[1] }
end
end
return assembleoutput(out, frame.args, qid, propertyID)
else
return props
end
end
p.getPropertyIDs = function(frame)
local args = frame.args
args.reqranks = setRanks(args.rank)
args.langobj = findLang(args.lang)
args.lang = args.langobj.code
args.noicon = tostring(parseParam(args.noicon or "", true))
local f = {}
f.args = args
local pid = mw.text.trim(args[1] or ""):upper()
local qid, props = parseInput(f, args[2], pid)
if not qid then return props end
if not props[1] then return nil end
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local maxvals = tonumber(args.maxvals) or 0
out = {}
for i, v in ipairs(props) do
local snak = v.mainsnak
if ( snak.datatype == "wikibase-item" )
and ( v.rank and args.reqranks[v.rank:sub(1, 1)] )
and ( snak.snaktype == "value" )
and ( sourced(v) or not onlysrc )
then
out[#out+1] = snak.datavalue.value.id
end
if maxvals > 0 and #out >= maxvals then break end
end
return assembleoutput(out, args, qid, pid)
end
p.getQualifierIDs = function(frame)
local args = frame.args
args.reqranks = setRanks(args.rank)
args.langobj = findLang(args.lang)
args.lang = args.langobj.code
args.noicon = tostring(parseParam(args.noicon or "", true))
local f = {}
f.args = args
local pid = mw.text.trim(args[1] or ""):upper()
local qid, props = parseInput(f, args[2], pid)
if not qid then return props end
if not props[1] then return nil end
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local maxvals = tonumber(args.maxvals) or 0
local qlist = args.qlist or ""
if qlist == "" then qlist = "ALL" end
qlist = qlist:gsub("[%p%s]+", " ") .. " "
out = {}
for i, v in ipairs(props) do
local snak = v.mainsnak
if ( v.rank and args.reqranks[v.rank:sub(1, 1)] )
and ( snak.snaktype == "value" )
and ( sourced(v) or not onlysrc )
then
if v.qualifiers then
for k1, v1 in pairs(v.qualifiers) do
if qlist == "ALL " or qlist:match(k1 .. " ") then
for i2, v2 in ipairs(v1) do
if v2.datatype == "wikibase-item" and v2.snaktype == "value" then
out[#out+1] = v2.datavalue.value.id
end
end
end
end
end
end
if maxvals > 0 and #out >= maxvals then break end
end
return assembleoutput(out, args, qid, pid)
end
p._getPropOfProp = function(args)
local paraset = tonumber(args.ps or args.parameterset or 0)
if paraset == 1 then
args.rank = "best"
args.fetchpornbasedata = "ALL"
args.onlysourced = "no"
args.noicon = "true"
elseif paraset == 2 then
args.rank = "best"
args.fetchpornbasedata = "ALL"
args.onlysourced = "no"
args.noicon = "true"
args.linked = "no"
args.pd = "true"
elseif paraset == 3 then
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 localval = mw.text.trim(args[1] or "")
if pid1 == "" or pid2 == "" then return nil end
local f = {}
f.args = args
local qid1, statements1 = parseInput(f, localval, pid1)
if not qid1 then return localval end
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local maxvals = tonumber(args.maxvals) or 0
local qualID = mw.text.trim(args.qual or ""):upper()
if qualID == "" then qualID = nil end
local out = {}
for k, v in ipairs(statements1) do
if not onlysrc or sourced(v) then
local snak = v.mainsnak
if snak.datatype == "wikibase-item" and snak.snaktype == "value" then
local qid2 = snak.datavalue.value.id
local statements2 = {}
if args.reqranks.b then
statements2 = mw.wikibase.getBestStatements(qid2, pid2)
else
statements2 = mw.wikibase.getAllStatements(qid2, pid2)
end
if statements2[1] then
local out2 = propertyvalueandquals(statements2, args, qualID)
out[#out+1] = assembleoutput(out2, args, qid2, pid2)
end
end
end
if maxvals > 0 and #out >= maxvals then break end
end
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
p.getAwardCat = function(frame)
frame.args.reqranks = setRanks(frame.args.rank)
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
local args = frame.args
args.sep = " "
local pid1 = args.prop1 or "P206"
local pid2 = args.prop2 or "P207"
if pid1 == "" or pid2 == "" then return nil end
local localval = mw.text.trim(args[1] or "")
local qid1, statements1 = parseInput(frame, localval, pid1)
if not qid1 then return localval end
local lp = (args.linkprefix or args.lp or ""):gsub('"', '')
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '')
local famname = ""
if sk == "" then
local p186 = mw.wikibase.getBestStatements(qid1, "P186")[1]
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or ""
famname = mw.wikibase.getSitelink(p186id) or ""
local pos = famname:find(":") or 0
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "")
if famname == "" then
local lbl = mw.wikibase.getLabel(p186id)
famname = lbl and mw.text.nowiki(lbl) or ""
end
end
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local maxvals = tonumber(args.maxvals) or 0
local qualID = mw.text.trim(args.qual or ""):upper()
if qualID == "" then qualID = nil end
local out = {}
for k, v in ipairs(statements1) do
if not onlysrc or sourced(v) then
local snak = v.mainsnak
if snak.datatype == "wikibase-item" and snak.snaktype == "value" then
local qid2 = snak.datavalue.value.id
local statements2 = {}
if args.reqranks.b then
statements2 = mw.wikibase.getBestStatements(qid2, pid2)
else
statements2 = mw.wikibase.getAllStatements(qid2, pid2)
end
if statements2[1] and statements2[1].mainsnak.snaktype == "value" then
local qid3 = statements2[1].mainsnak.datavalue.value.id
local sitelink = mw.wikibase.getSitelink(qid3)
if not sitelink then
local lbl = mw.wikibase.getLabelByLang(qid3, "pbc")
if lbl then
if lbl:sub(1,9) == "Category:" then
sitelink = mw.text.nowiki(lbl)
else
sitelink = "Category:" .. mw.text.nowiki(lbl)
end
end
end
if sitelink then
if sk ~= "" then
out[#out+1] = "[[" .. lp .. sitelink .. "|" .. sk .. "]]"
elseif famname ~= "" then
out[#out+1] = "[[" .. lp .. sitelink .. "|" .. famname .. "]]"
else
out[#out+1] = "[[" .. lp .. sitelink .. "]]"
end
end
end
end
end
if maxvals > 0 and #out >= maxvals then break end
end
return assembleoutput(out, args, qid1, pid1)
end
p.getIntersectCat = function(frame)
frame.args.reqranks = setRanks(frame.args.rank)
frame.args.langobj = findLang(frame.args.lang)
frame.args.lang = frame.args.langobj.code
local args = frame.args
args.sep = " "
args.linked = "no"
local pid1 = args.prop1 or "P124"
local pid2 = args.prop2 or "P133"
if pid1 == "" or pid2 == "" then return nil end
local qid, statements1 = parseInput(frame, "", pid1)
if not qid then return nil end
local qid, statements2 = parseInput(frame, "", pid2)
if not qid then return nil end
local subs_exists, subs = pcall(mw.loadData, "Module:PornBaseDataIB/subs")
local join = args.join or ""
local onlysrc = parseParam(args.onlysourced or args.osd, true)
local maxvals = tonumber(args.maxvals) or 0
local lp = (args.linkprefix or args.lp or ""):gsub('"', '')
local sk = (args.sortkey or args.sk or ""):gsub('["-.]', '')
local famname = ""
if sk == "" then
local p186 = mw.wikibase.getBestStatements(qid, "P186")[1]
local p186id = p186 and p186.mainsnak.snaktype == "value" and p186.mainsnak.datavalue.value.id or ""
famname = mw.wikibase.getSitelink(p186id) or ""
local pos = famname:find(":") or 0
famname = famname:sub(pos+1):gsub("%s%(.+%)$", "")
if famname == "" then
local lbl = mw.wikibase.getLabel(p186id)
famname = lbl and mw.text.nowiki(lbl) or ""
end
end
local cat1 = {}
for k, v in ipairs(statements1) do
if not onlysrc or sourced(v) then
local pvalID = (v.mainsnak.snaktype == "value") and v.mainsnak.datavalue.value.id
if pvalID then
local p50 = mw.wikibase.getBestStatements(pvalID, "P50")[1]
if p50 and p50.mainsnak.snaktype == "value" then
local tmcID = p50.mainsnak.datavalue.value.id
local cat = mw.wikibase.getSitelink(tmcID)
if not cat then
local lbl = mw.wikibase.getLabelByLang(tmcID, "pbc")
if lbl then
if lbl:sub(1,9) == "Category:" then
cat = mw.text.nowiki(lbl)
else
cat = "Category:" .. mw.text.nowiki(lbl)
end
end
end
cat1[#cat1+1] = cat
end
end
end
if maxvals > 0 and #cat1 >= maxvals then break end
end
local cat2 = {}
for k, v in ipairs(statements2) do
if not onlysrc or sourced(v) then
local cat = rendersnak(v, args)
if subs[cat] then cat = subs[cat] end
cat2[#cat2+1] = cat
end
if maxvals > 0 and #cat2 >= maxvals then break end
end
out = {}
for k1, v1 in ipairs(cat1) do
for k2, v2 in ipairs(cat2) do
if sk ~= "" then
out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "|" .. sk .. "]]"
elseif famname ~= "" then
out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "|" .. famname .. "]]"
else
out[#out+1] = "[[" .. lp .. v1 .. " " .. join .. " " .. v2 .. "]]"
end
end
end
args.noicon = "true"
return assembleoutput(out, args, qid, pid1)
end
p.qualsToTable = function(frame)
local args = frame.args
local quals = args.quals or ""
if quals == "" then return "" end
args.reqranks = setRanks(args.rank)
local propertyID = mw.text.trim(args[1] or "")
local f = {}
f.args = args
local entityid, props = parseInput(f, "", propertyID)
if not entityid then return "" end
args.langobj = findLang(args.lang)
args.lang = args.langobj.code
local pval = args.pval or ""
local qplist = mw.text.split(quals, "%p")
for i, v in ipairs(qplist) do
qplist[i] = mw.text.trim(v):upper()
end
local col1 = args.firstcol or ""
if col1 ~= "" then
col1 = col1 .. "</td><td>"
end
local emptycell = args.emptycell or " "
local qvals = {}
for i, v in ipairs(props) do
local skip = false
if pval ~= "" then
local pid = v.mainsnak.datavalue and v.mainsnak.datavalue.value.id
if pid ~= pval then skip = true end
end
if not skip then
local qval = {}
local vqualifiers = v.qualifiers or {}
for i1, v1 in ipairs(qplist) do
local qv, qtype
if vqualifiers[v1] then
qtype = vqualifiers[v1][1].datatype
if qtype == "time" then
if vqualifiers[v1][1].snaktype == "value" then
qv = mw.wikibase.renderSnak(vqualifiers[v1][1])
qv = frame:expandTemplate{title="dts", args={qv}}
else
qv = "?"
end
elseif qtype == "url" then
if vqualifiers[v1][1].snaktype == "value" then
qv = mw.wikibase.renderSnak(vqualifiers[v1][1])
local display = mw.ustring.match( mw.uri.decode(qv, "WIKI"), "([%w ]+)$" )
if display then
qv = "[" .. qv .. " " .. display .. "]"
end
end
else
qv = mw.wikibase.formatValue(vqualifiers[v1][1])
end
end
qval[i1] = qv or emptycell
end
qvals[#qvals+1] = qval
end
end
local out = {}
for i, v in ipairs(qvals) do
out[i] = "<tr><td>" .. col1 .. table.concat(qvals[i], "</td><td>") .. "</td></tr>"
end
return table.concat(out, "\n")
end
p.getGlobe = function(frame)
local qid = frame.args.qid or frame.args[1] or ""
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
local coords = mw.wikibase.getBestStatements(qid, "P48")[1]
local globeid
if coords and coords.mainsnak.snaktype == "value" then
globeid = coords.mainsnak.datavalue.value.globe:match("(Q%d+)")
end
return globeid
end
p.getCommonsLink = function(frame)
local oc = frame.args.onlycat or frame.args.onlycategories
local fb = parseParam(frame.args.fallback or frame.args.fb, true)
return _getCommonslink(frame.args.qid, oc, fb)
end
p.getSiteLink = function(frame)
return _getSitelink(frame.args.qid, frame.args.wiki or mw.text.trim(frame.args[1] or ""))
end
p.getLink = function(frame)
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
if itemID == "" then return end
local sitelink = mw.wikibase.getSitelink(itemID)
local label = labelOrId(itemID)
if sitelink then
return "[[:" .. sitelink .. "|" .. label .. "]]"
else
return label
end
end
p.getLabel = function(frame)
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
if itemID == "" then return end
local lang = frame.args.lang or ""
if lang == "" then lang = nil end
local label = labelOrId(itemID, lang)
return label
end
p.label = function(frame)
local qid = mw.text.trim(frame.args[1] or frame.args.qid or "")
if qid == "" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return end
local lang = frame.args.lang or ""
if lang == "" then lang = nil end
local label, success = labelOrId(qid, lang)
if success then return label end
end
p.getAT = function(frame)
local itemID = mw.text.trim(frame.args[1] or frame.args.qid or "")
if itemID == "" then return end
return mw.wikibase.getSitelink(itemID)
end
p.getDescription = function(frame)
local desc = mw.text.trim(frame.args[1] or "")
local itemID = mw.text.trim(frame.args.qid or "")
if itemID == "" then itemID = nil end
if desc:lower() == 'pornbasedata' then
return mw.wikibase.getDescription(itemID)
elseif desc:lower() == 'none' then
return nil
else
return desc
end
end
p.getAliases = function(frame)
local args = frame.args
local fieldname = args.name or ""
if fieldname == "" then fieldname = "alias" end
local blacklist = args.suppressfields or args.spf or ""
if blacklist:find(fieldname) then return nil end
local localval = mw.text.trim(args[1] or "")
if localval ~= "" then return localval end
local whitelist = args.fetchpornbasedata or args.fpbd or ""
if whitelist == "" then whitelist = "NONE" end
if not (whitelist == 'ALL' or whitelist:find(fieldname)) then return nil end
local qid = mw.text.trim(args.qid or "")
if qid == "" then qid = nil end
local entity = mw.wikibase.getEntity(qid)
if not entity then return nil end
local aliases = entity.aliases
if not aliases then return nil end
if not qid then qid= mw.wikibase.getEntityIdForCurrentPage() end
args.langobj = findLang(args.lang)
local langcode = args.langobj.code
args.lang = langcode
local out = {}
for k1, v1 in pairs(aliases) do
if v1[1].language == langcode then
for k1, v2 in ipairs(v1) do
out[#out+1] = v2.value
end
break
end
end
return assembleoutput(out, args, qid)
end
p.pageId = function(frame)
return mw.wikibase.getEntityIdForCurrentPage()
end
p.formatDate = function(frame)
return format_Date(frame.args[1], frame.args.df, frame.args.bc)
end
p.getImageLegend = function(frame)
local id = frame.args.id
if id and (#id == 0) then
id = nil
end
local lang = frame.args.lang
if (not lang) or (#lang < 2) then
lang = mw.language.getContentLanguage().code
end
local input_parm = mw.text.trim(frame.args[1] or "")
if input_parm == "FETCH_WIKIDATA" then
local ent = mw.wikibase.getEntity(id)
local imgs
if ent and ent.claims then
imgs = ent.claims.P470
end
local imglbl
if imgs then
for k1, v1 in pairs(imgs) do
if v1.rank == "preferred" and v1.qualifiers and v1.qualifiers.P523 then
local imglbls = v1.qualifiers.P523
for k2, v2 in pairs(imglbls) do
if v2.datavalue.value.language == lang then
imglbl = v2.datavalue.value.text
break
end
end
end
end
if (not imglbl) then
for k1, v1 in pairs(imgs) do
if v1.rank == "normal" and v1.qualifiers and v1.qualifiers.P523 then
local imglbls = v1.qualifiers.P523
for k2, v2 in pairs(imglbls) do
if v2.datavalue.value.language == lang then
imglbl = v2.datavalue.value.text
break
end
end
end
end
end
end
return imglbl
else
return input_parm
end
end
p.location = function(frame)
local debug = (frame.args.debug or ""):sub(1, 1):lower()
if debug == "" then debug = "n" end
local qid = mw.text.trim(frame.args.qid or frame.args[1] or ""):upper()
if qid == "" then qid=mw.wikibase.getEntityIdForCurrentPage() end
if not qid then
if debug ~= "n" then
return i18n.errors["entity-not-found"]
else
return nil
end
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
p.checkBlacklist = function(frame)
local blacklist = frame.args.suppressfields or frame.args.spf or ""
local fieldname = frame.args.name or ""
if blacklist ~= "" and fieldname ~= "" then
if blacklist:find(fieldname) then
return false
else
return true
end
else
return true
end
end
p.emptyor = function(frame)
local s = frame.args[1] or ""
if s == "" then return nil end
local sx = s:gsub("%s", ""):gsub("<[^>]*>", ""):gsub("%p", "")
if sx == "" then
return nil
else
return s
end
end
p.labelorid = function(frame)
return (labelOrId(frame.args.qid or frame.args[1]))
end
p.getLang = function(frame)
local style = (frame.args.style or ""):lower()
local langcode = mw.language.getContentLanguage().code
if style == "full" then
return mw.language.fetchLanguageName( langcode )
end
return langcode
end
p.getItemLangCode = function(frame)
return _getItemLangCode(frame.args.qid or frame.args[1])
end
p.findLanguage = function(frame)
return findLang(frame.args.lang or frame.args[1]).code
end
p.getQid = function(frame)
local qid = (frame.args.qid or ""):upper()
if qid ~= "" then return qid end
qid = mw.wikibase.getEntityIdForCurrentPage()
if qid then
local prop521 = mw.wikibase.getBestStatements(qid, "P521")
if prop521[1] then
local mctid = prop521[1].mainsnak.datavalue.value.id
if mctid then return mctid end
end
end
return qid
end
p._followQid = function(args)
local qid = (args.qid or ""):upper()
local all = parseParam(args.all, false)
if qid == "" then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
if not qid then return nil end
local out = {}
local props = (args.props or ""):upper()
if props ~= "" then
for p in mw.text.gsplit(props, "%p") do
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
if all then
out[#out+1] = linkedid
else
return linkedid
end
end
end
end
end
if #out > 0 then
return table.concat(out, " ")
else
return qid
end
end
p.followQid = function(frame)
return p._followQid(frame.args)
end
p.globalSiteID = function(frame)
return mw.wikibase.getGlobalSiteId()
end
p.siteID = function(frame)
local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
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
p.projID = function(frame)
local txtlang = frame:preprocess( "{{int:lang}}" ) or ""
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
p.formatNumber = function(frame)
local lang
local num = tonumber(frame.args[1] or frame.args.num) or 0
lang = findLang(frame.args.lang)
return lang:formatNum( num )
end
p.examine = function( frame )
local args
if frame.args[1] or frame.args.pid or frame.args.qid then
args = frame.args
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
local q1 = qid:sub(1,1)
if pid:sub(1,1) ~= "P" then return "No property supplied" end
if q1 ~= "Q" and q1 ~= "M" then qid = mw.wikibase.getEntityIdForCurrentPage() end
if not qid then return "No item for this page" end
return "<pre>" .. mw.dumpObject( mw.wikibase.getAllStatements( qid, pid ) ) .. "</pre>"
end
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 "P1"):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
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 stats[1].mainsnak.datatype == "wikibase-item" then
for k, v in pairs( stats ) do
ms = v.mainsnak
if ranks[v.rank:sub(1,1)] and ms.snaktype == "value" and ms.datavalue.value.id == val then
return val
end
end
end
return nil
end
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( "^([^/]+)/$", "%1" ):gsub("%/", "<wbr/>/"):gsub("%.", "<wbr/>.")
return '<span class="url">[' .. prot .. addr .. " " .. disp .. "]</span> " .. icon
end
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 prop52 = mw.wikibase.getBestStatements(qid, "P52")
for k, v in pairs(prop52) do
if v.mainsnak.snaktype == "value" then
urls[#urls+1] = v.mainsnak.datavalue.value
if v.qualifiers and v.qualifiers["P208"] then
local au = v.qualifiers["P208"][1]
if au.snaktype == "value" then
quals[#urls] = au.datavalue.value
end
end
end
end
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, "P52")
end
local ret = ""
if #out > 1 then
ret = mw.getCurrentFrame():expandTemplate{title = "ubl", args = out}
else
ret = out[1]
end
return ret
end
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
local out = {}
for k, v in pairs(labels) do
out[#out+1] = v.value .. " (" .. v.language .. ")"
end
return table.concat(out, "; ")
end
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
local out = {}
for k, v in pairs(descriptions) do
out[#out+1] = v.value .. " (" .. v.language .. ")"
end
return table.concat(out, "; ")
end
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
local 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
p.showNoLinks = function(frame)
local out = {}
for k, v in pairs(donotlink) do
out[#out+1] = k
end
table.sort( out )
return table.concat(out, "; ")
end
function p.checkValidity(frame)
local id = mw.text.trim(frame.args[1] or "")
if mw.wikibase.isValidEntityId(id) then
return true
else
return false
end
end
function p.getEntityFromTitle(frame)
local args=frame.args
if not args[1] then args=frame:getParent().args end
if not args[1] then return nil end
local title = mw.text.trim(args[1])
local site = args.site or ""
local showdab = parseParam(args.showdab, true)
qid = mw.wikibase.getEntityIdForTitle(title, site)
if qid then
local prop1 = mw.wikibase.getBestStatements(qid, "P1")[1]
if not showdab and prop1 and prop1.mainsnak.datavalue.value.id == "Q220" then
return nil
else
return qid
end
end
end
function p.getDatePrecision(frame)
local args=frame.args
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 "")
if prop == "" then return default end
local qid = args.qid or ""
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 stat = mw.wikibase.getBestStatements(qid, prop)
for i, v in ipairs(stat) do
local prec = (onlysrc == false or sourced(v))
and v.mainsnak.datavalue
and v.mainsnak.datavalue.value
and v.mainsnak.datavalue.value.precision
if prec then return prec end
end
return default
end
return p