local p = {}
local wikidata = require 'Module:Wikidata'
local lang = mw.getCurrentFrame():preprocess('{{int:lang}}')
-- LISTS
local listtypes = {
exhibition = { -- works in a catalogue raisonné, columns = 1: catalogue number, 2: image, 3: artowrkbox
columns = {
[1] = function(item, catalogue, exhibition) -- catalogue number
local val
if catalogue then -- first try to get the value from the catalogue, most reliable
val = wikidata.formatStatements({entity=item, property = 'P528', qualifier='P972', qualifiervalue = catalogue, lang=lang})
end
if (not val) and exhibition then
val = wikidata.showQualifier({entity=item, property = 'P608', qualifiers={'P528'}, targetvalue = exhibition, lang=lang})
end
return val
end,
[2] = 'image',
[3]= function(item) return require 'Module:Artwork'.artworkbox(item) end
},
sortkey = 1, -- catalogue as the sortkey
query = function(item, catalogue) return 'claim[528]{claim[972:' .. catalogue .. ']}' end,
},
['catalogue raisonné']= { -- works in a catalogue raisonné, columns = 1: catalogue number, 2: image, 3: artowrkbox
columns = {
[1] = function(item, catalogue) -- catalogue number
return wikidata.formatStatements({entity=item, property = 'P528', qualifier='P972', qualifiervalue = catalogue, lang=lang})
end,
[2] = 'image',
[3]= function(item) return require 'Module:Artwork'.artworkbox(item) end
},
sortkey = 1, -- catalogue as the sortkey
query = function(item, catalogue) return 'claim[528]{claim[972:' .. catalogue .. ']}' end,
},
['museum collection'] = { --museum collection etc.
columns = {
[1] = 'image',
[2]= function(item) return require 'Module:Artwork'.artworkbox(item) end,
[3] = function(item, catalogue, collection) -- accesssion number
return wikidata.formatStatements({entity=item, property = 'P217', qualifier='P195', qualifiervalue = collection, lang=lang})
end,
},
sortkey = function(item)
-- sort by artist and by date, and sort artists by birth date
local artist = wikidata.formatStatements{item = item, property = 'P170', numval = 1, displayformat = 'raw'}
local birthdate = '?'
if artist then
birthdate = wikidata.formatStatements{item = artist, property = 'P569', displayformat = 'raw', numval = 1}
end
local workdate = wikidata.formatStatements{item = item, property = 'P571', numval=1, displayformat = 'raw'}
return (birthdate or '?') .. ' ' .. (artist or '?') .. ' ' .. (workdate or '?')
end,
query = function(item, collection) return 'claim[195:' .. collection .. ']' end,
},
artwork = { -- artwork without any additional parameter
columns = {
[1] = 'image',
[2] = function(item) return require 'Module:Artwork'.artworkbox(item) end,
},
sortkey = function(item)
-- sort be artist then by date, and artists by birth date
local artist = wikidata.formatStatements{item = item, property = 'P170', numval = 1, displayformat = 'raw'}
local birthdate = '?'
if artist then
birthdate = wikidata.formatStatements{item = artist, property = 'P569', displayformat = 'raw', numval = 1}
end
local workdate = wikidata.formatStatements{item = item, property = 'P571', numval=1, displayformat = 'raw'}
return (birthdate or '?') .. ' ' .. (artist or '?') .. ' ' .. (workdate or '?')
end
},
default = {
columns = {
[1] = 'image',
[2] = function(item) return wikidata.formatEntity(item, {}) end,
}
}
}
local fb = require 'Module:Fallback'
local i18n = {
wdqlink = {
en = 'Update',
fr = 'Mettre à jour',
},
invalidlisttype = {
en = 'You requested an unknown type of list',
fr = 'Type de liste inconnu',
}
}
local function langSwitch(msg)
return fb._langSwitch(msg, lang)
end
-- Commonly used data
local function makeimage(entity)
local image = wikidata.formatStatements({entity=entity, property='P18', numval=1, lang=lang})
return '[[File:' .. (image or 'Missing image text.png') .. '|200px]]'
end
local function before(a, b) -- return true if a is a smaller sortkey than b
if tonumber(a) and tonumber(b) then -- if both are numeric
return tonumber(a) < tonumber(b)
end
a, b = tostring(a), tostring(b)
if tonumber(string.sub(a, 1,1)) and tonumber(string.sub(b, 1, 1)) then -- if they are numeric, but with something afterwards like catalogue number 12A
local newa, newb = '', ''
local i = 1 -- only keeps the numeric first part of the value (the numeric one) could be better
while tonumber(string.sub(a, 1, i)) and i <= string.len(a) do
newa = string.sub(a, 1, i)
i = i + 1
end
i = 1
while tonumber(string.sub(b, 1, i)) and i <= string.len(b) do
newb = string.sub(b, 1, i)
i = i + 1
end
return tonumber(newa) < tonumber(newb)
end
return a < b -- default: sort alphabetically
end
local function sortrows(rows)
table.sort(rows, function(a,b) return before(a.sortkey, b.sortkey) end)
return rows
end
local function getvalue(entity, query, catalogue, topic)
local querylibrary = { -- maps keyword to the function it represents
image = makeimage
}
-- if query is a string, look for the function it represents
if type(query) == 'string' and querylibrary[query] then
query = querylibrary[query]
end
-- if query is is a function, expand it
if type(query) == 'function' then
return query(entity, catalogue, topic)
end
return query
end
local function wdqlink(query, topic)
if not query then
return ''
end
query = getvalue(entity, query, topic)
query = string.gsub(query, 'Q', '')
local link = mw.getCurrentFrame():preprocess('https://tools.wmflabs.org/listeria/index.php?action=update&lang=wikidata&page={{FULLPAGENAMEE}}')
local text = langSwitch(i18n.wdqlink)
return '[' .. link .. ' ' .. text .. ']'
end
local function splitlist(list)
if type(list) == 'table' then
return list
else
return mw.text.split(list, ',')
end
end
local function makerow(item, columns, sortkey, catalogue, topic)
local entity = mw.wikibase.getEntityObject('Q' .. item)
-- get cell values
local vals = {}
for k, l in pairs(columns) do
local val = getvalue(entity, l, catalogue, topic) or ''
table.insert(vals, val)
end
-- add sortkey
local key
if type(sortkey) == 'function' then
key = sortkey(entity)
elseif type(sortkey) == 'number' then -- column number sortkey is the key
key = vals[sortkey]
end
if not key then
key = '?'
end
-- make html object
local content = mw.html.create('tr')
for i, j in pairs(vals) do
content:tag('td'):wikitext(j)
end
content:done()
return {sortkey = key, content = content}
end
function p.makelist(items, columns, sortkey, listtype, query, catalogue, topic, class, style)
local rows = {}
items = splitlist(items)
-- if listtype, formats according to predefined rules
if not columns then
listtype = listtype or 'default'
local listparams = listtypes[listtype]
if not listparams then
return langSwitch(i18n['invalidlisttype'])
end
if not query or query == '' then -- should not override a more accuate query parameter (that may be provided to avoid huge list)
query = listparams.query
end
columns, sortkey, class = listparams.columns, listparams.sortkey, listparams.class
end
for i, item in pairs(items) do
local newrow = makerow(item, columns, sortkey, catalogue, topic)
table.insert(rows, newrow)
end
local header = mw.html.create('tr')
for i, j in pairs(columns) do
local text
local sorttype
if type(j) == 'table' then
text = j.header
sorttype = j.sorttype
end
local val = mw.html.create('th')
:addClass(sorttype)
:wikitext(text or ' ')
header:node(val)
end
header:done()
if not class then
class = 'wikitable sortable'
end
if not style then
style = {width = '100%'}
end
local outtable = mw.html.create('table')
:addClass(class)
:css(style)
:node(header)
rows = sortrows(rows)
-- add rows
for i, row in pairs(rows) do
outtable:node(row.content)
end
local link = wdqlink(query, topic)
return link .. tostring(outtable)
end
function p.listfromFrame(frame)
local nargs = {}
for i, j in pairs(frame.args) do
if j ~= '' then nargs[i] = j end
end
return p.makelist(nargs.items, nil, nil, nargs.listtype, nargs.query, nargs.catalogue, nargs.topic)
end
return p