Module:Wikidata description/sandbox
Lua
Documentation for this module may be created at Module:Wikidata description/sandbox/doc
Code
--script that retrieves basic data stored in Wikidata, for the datamodel, see https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua
local p = {}
local linguistic = require('Module:Linguistic')
local selectClaims = require "Module:Wikidata/GetClaims"
local tools = require "Module:Wikidata/Tools"
local entities = require "Module:Wikidata/FormatEntity"
local dates = require "Module:Wikidata/Dates"
local weblink = require "Module:Weblink"
local fb = require('Module:Fallback')
local i18nmessages = mw.loadData('Module:i18n/wikidata')
-- Wiki-specific parameters
local defaultlang = mw.getCurrentFrame():preprocess("{{int:lang}}")
local defaultlink = 'wikidata'
local function i18n(str, lang)
local message = i18nmessages[str]
if type(message) == 'string' then
return message
end
return fb._langSwitch(message, lang or defaultlang)
end
local function formatError( key, text )
return error(i18n(key) .. " " .. (text or ''))
end
p.getClaims = selectClaims.getClaims
local function removeBlanks(args)
for i = #args, 1, -1 do
if (args[i] == '') or (args[i] == '-') then
table.remove(args, i)
end
end
return args
end
local function formatTheUnknown() -- voir si on peut accorder/adapter l'usage de "inconnu"
return i18n('somevalue')
end
local function getQualifiers(statement, qualifs, params)
if not statement.qualifiers then
return nil
end
if type(qualifs) == "string" then
qualifs = mw.text.split(qualifs, ',')
end
local vals = {}
for i, j in pairs(qualifs) do
j = string.upper(j)
if statement.qualifiers[j] then
local inserted = false
if statement.qualifiers[j][1].datatype == 'monolingualtext' then
local in_preferred_lang
for _, language in pairs(fb.fblist(params.lang or defaultlang)) do
for _, snak in pairs(statement.qualifiers[j]) do
if isInLanguage(snak, language) then
in_preferred_lang = snak
break
end
end
if in_preferred_lang then
break
end
end
if in_preferred_lang then
table.insert(vals, in_preferred_lang)
inserted = true
end
end
if not inserted then
for _, snak in pairs(statement.qualifiers[j]) do
table.insert(vals, snak)
end
end
end
end
if #vals == 0 then
return nil
end
return vals
end
function p.formatSnak(snak, params)
local displayformat = params.displayformat
local datatype = snak.datatype
-- "special value" : novalue and somevalue
if snak.snaktype == 'somevalue' then
return formatTheUnknown()
elseif snak.snaktype == 'novalue' then
return i18n('novalue') --todo
end
local value = snak.datavalue.value
-- user-defined displayformat
if type(displayformat) == 'function' then
return displayformat(snak, params)
end
local displayformat = params.displayformat
if type(displayformat) == 'function' then
return displayformat(snak, params)
end
if datatype == 'wikibase-item' then
return entities.formatEntity(tools.getId(snak), params)
end
if datatype == 'url' then
return weblink.makelink(value, params.text, params.displayformat)
end
if datatype == 'math' then
return mw.getCurrentFrame():extensionTag( "math", value)
end
if (datatype == 'string') or (datatype == 'external-id') or (datatype == 'commonsMedia') then
if params.urlpattern then
local urlpattern = params.urlpattern
if type(urlpattern) == 'function' then
urlpattern = urlpattern(value)
end
value = '[' .. mw.ustring.gsub(urlpattern, '$1', value) .. ' ' .. (params.text or value) .. ']'
end
return value
end
if datatype == 'time' then -- format example: +00000001809-02-12T00:00:00Z
return dates.formatTimeSnak(snak, params)
end
if datatype == 'globe-coordinate' then
-- default return a table with latitude, longitude, precision and globe that can be used by another module
if displayformat == 'latitude' then
return value.latitude
elseif displayformat == 'longitude' then
return value.longitude
elseif displayformat == 'qualifier' then
local coord = require 'Module:Coordinates'
value.globe = require('Module:Wikidata/Globes')[value.globe]
value.precision = nil
return coord._coord(value)
else
value.globe = require('Module:Wikidata/Globes')[value.globe] -- get English name for geohack
return value
end
end
if datatype == 'quantity' then -- todo : gérer les paramètre précision
if displayformat == 'raw' then
return tonumber(value.amount)
else
local formatNum = require 'Module:Formatnum'
local number = formatNum.formatNum(value.amount)
local unit = mw.ustring.match(value.unit, '(Q%d+)')
if unit then
number = number .. ' ' .. entities.formatEntity(unit, params)
end
end
end
if datatype == 'monolingualtext' then
if value.language == defaultlang then
return value.text
else
return '<span lang="' .. value.language .. '">' .. value.text .. '</span>'
end
end
return formatError('unknown-datavalue-type', datatype )
end
function p.formatStatementQualifiers(statement, qualifs, params)
if not params then params = {} end
local qualiftable = getQualifiers(statement, qualifs, params)
if not qualiftable then
return nil
end
for i, j in pairs(qualiftable) do
local params = params
if j.datatype == 'globe-coordinate' then
params.displayformat = 'qualifier'
end
qualiftable[i] = p.formatSnak(j, params)
end
return linguistic.conj(qualiftable, params.lang or defaultlang)
end
function p.formatStatement( statement, args )
if not statement.type or statement.type ~= 'statement' then
return formatError( 'unknown-claim-type', statement.type )
end
if not args then args = {} end
local lang = args.lang or defaultlang
local str = p.formatSnak( statement.mainsnak, args )
local qualifs = args.showqualifiers
if qualifs then
local qualifStr = p.formatStatementQualifiers(statement, qualifs, args)
if qualifStr then
if args.delimiter then
str = str .. args.delimiter .. qualifStr
else
str = str .. " (" .. qualifStr .. ")" -- str .. linguistic.inparentheses(qualifStr, lang)
end
end
end
if args.showdate then -- when "showdate and p.chronosort are both set, date retrieval is performed twice
local date = dates.getFormattedDate(statement, params)
if date then
str = str .. ' <small>(' .. date ..')</small>' -- str .. linguistic.inparentheses(date, lang)
end
end
if args.showsource and statement.references then
local cite = require 'Module:Cite'
local frame = mw.getCurrentFrame()
local sourcestring = ''
for i, ref in pairs(statement.references) do
if ref.snaks.P248 then
for j, source in pairs(ref.snaks.P248) do
if not tools.isSpecial(source) then
local page
if ref.snaks.P304 and not tools.isSpecial(ref.snaks.P304[1]) then
page = ref.snaks.P304[1].datavalue.value
end
local s = cite.citeitem('Q' .. source.datavalue.value['numeric-id'], lang, page)
s = frame:extensionTag( 'ref', s )
sourcestring = sourcestring .. s
end
end
elseif ref.snaks.P854 and not tools.isSpecial(ref.snaks.P854[1]) then
s = frame:extensionTag( 'ref', p.getDatavalue(ref.snaks.P854[1]) )
sourcestring = sourcestring .. s
end
end
str = str .. sourcestring
end
return str
end
function p._getDescription(entity, lang)
if not entity then
return i18n('no description entity')
end
if type(entity) == "string" and ( (not lang) or (lang == defaultlang) ) then
return mw.wikibase.description(entity)
end
entity = p.getEntity(entity)
local descriptions = entity.descriptions
if not descriptions then
return i18n('no description descriptions')
end
local langlist = fb.fblist(lang or defaultlang) -- list of fallback languages if no label in the desired language
for i, lg in pairs(langlist) do
if descriptions[lg] then
return descriptions[lg].value
end
end
return i18n('no description end')
end
-- == FUNCTIONS HANDLING SEVERAL STATEMENTS ===
function p.stringTable(args) -- find the relevant claims, and formats them as a list of strings
-- getClaims
local claims = p.getClaims(args)
if not claims then
return nil
end
-- define the formatter function
local formatterFun = p.formatStatement
if args.type == "date" then
formatterFun = dates.getFormattedDate
elseif args.type == "qualifiers" then
formatterFun = formatStatementQualifiers
end
-- format claims
for i = #claims, 1, -1 do
claims[i] = formatterFun(claims[i], args)
if not claims[i] then
table.remove(claims, i)
end
end
return claims
end
function p.formatStatements( args )--Format statements and concat them cleanly
--If a value is already set, use it
if args.value == '-' then
return nil
end
if args.value then
return args.value
end
-- obsolete parameters
if args.item then
args.entity = args.item
end
local values = p.stringTable(args) -- gets statements, and format each of them
if not values then
return nil
end
return linguistic.conj(values, args.lang or defaultlang, args.conjtype) -- concatenate them
end
-- == FRAME FUNCTIONS ==
function p.getDescription(frame) -- simple for simple templates like {{Q|}}}
local entity = frame.args.entity
local lang = frame.args.lang
return p._getDescription(entity, lang)
end
function p.formatStatementsE(frame)
local args = {}
if frame == mw.getCurrentFrame() then
args = frame:getParent().args -- paramètres du modèle appelant (est-ce vraiment une bonne idée ?)
for k, v in pairs(frame.args) do
args[k] = v
end
else
args = frame
end
args = removeBlanks(args)
return p.formatStatements( args )
end
function p._getLabel(entity, args)
return entities.formatEntity(entity, args)
end
function p.getLabel(frame) -- simple for simple templates like {{Q|}}}
local args = removeBlanks(frame.args)
local entity = args.entity or args[1]
if string.sub(entity, 1, 10) == 'Property:P' then
entity = string.sub(entity, 10)
elseif (string.sub(entity, 1, 1) ~= 'P' and string.sub(entity, 1, 1) ~= 'Q') or (not tonumber(string.sub(entity, 2))) then
return i18n('invalid-id')
end
return entities.formatEntity(entity, args)
end
function p._wikidataDate(prop, item, params)
local claims = p.getClaims{entity = item, property = prop}
if not claims then
return nil
end
params = params or {}
local vals = {}
for i, j in pairs(claims) do
local v = dates.getFormattedDate(j, params)
if v then
table.insert(vals, v)
end
end
local str = linguistic.conj(vals, params.conjtype or 'or')
if not str then
return
end
return str
end
function p.wikidataDate(frame)
p._wikidataDate(frame.args[property], frame.args[params], frame.args)
end
function p._main_date(entity)
-- tries P580/P582
local startpoint = p._wikidataDate('P580', entity)
local endpoint = p._wikidataDate('P582', entity)
local str
if startpoint or endpoint then
str = (startpoint or '') .. ' - ' .. (endpoint or '')
end
if str then
return str
end
--default : P585
return p._wikidataDate('P585', entity)
end
function p.main_date(frame)
return p._main_date(frame.args[1])
end
-- returns the page id (Q...) of the current page or nothing of the page is not connected to Wikidata
function p.pageId(frame)
local entity = mw.wikibase.getEntityObject()
if not entity then return nil else return entity.id end
end
return p