Module:Artwork

From Wikidata
Jump to navigation Jump to search
Lua
CodeDiscussionLinksLink count SubpagesDocumentationTestsResultsSandboxLive code All modules

Code

local p = {}

local fb = require('Module:Fallback')
local langSwitch = fb._langSwitch
local linguistic =  require('Module:Linguistic')
local wikidata = require('Module:Wikidata')
local persondescription = require('Module:Person description')
local utils = require('Module:Wikidata/utils')
local daterange = require('Module:Daterange')

local i18n = {
	history = {
		en = 'Artwork history',
		fr = 'Historique de l\'oeuvre',
		pl = 'Historia dzieła sztuki',
	},
	nocatnumber = {
		en = 'no catalogue numer',
		fr = 'pas de numéro de catalogue',
		pl = 'brak numeru katalogowego',
	},
	topic = {
		en = 'Depicted topic',
		fr = 'Sujet représenté',
		pl = 'Przedstawiony temat',
	},
	topics = {
		en = 'Depicted topics',
		fr = 'Sujets représentés',
		pl = 'Przedstawione tematy',
	},
	photo = {
		en = 'Photo',
		fr = 'Photo',
		pl = 'Ilustracja',
	},
	missinglicense = {
		en = 'Please provide a licence',
		fr = 'Veuillez fournir une licence',
		pl = 'Proszę wprowadź licencję',
	},
}
---- i18n functions --
local function colon(lang)
	return mw.message.newFallbackSequence( "colon" ):inLanguage(lang):plain()
end

local function catnumber(num, lang) -- catalogue number
	local v = langSwitch({
		de = function(num) return 'Katnr. ' .. num end,
		en = function(num) return 'cat. no. ' .. num end,
		fr = function(num) return 'n°' .. num end,
		nl = function(num) return 'cat.nr. ' .. num end,
	}, lang)
	return v(num, lang)
end

local function translate(message, lang)
	return langSwitch(i18n[message], lang)
end
----
local function buildcreator(item, lang)
	return  wikidata.getClaims({entity=item, property='P170', lang=lang})	
end

local function builddepicted(item, lang) -- create list of things depicted in the artwork

	local depicttable = wikidata.getClaims({item=item, property = 'P180', rank = 'valid'})
	if not depicttable then
		return nil
	end
	local function crotoslink(item)
		local id = string.sub(item, 2)
	 	return ' ([http://www.zone47.com/crotos/?p180=' .. id ..' Crotos])'
	end

	local function preferreddescription(item, lang) -- description of the "preferred" P180 values
		if utils.isinstance(item, 'Q215627') then --description for people
			return persondescription.shortdescription(item, lang) .. crotoslink(item)
		else
			return linguistic.conj({wikidata.formatEntity(item, lang), wikidata._getDescription(obj, lang)}, lang, 'comma') .. crotoslink(id)
		end
	end
	local function normaldescription(item, lang) -- faster description for those with rank = "normal"
		return wikidata.formatEntity(item, {lang=lang}) .. crotoslink(item)
	end
	
	local maintopics, othertopics = {}, {}
	for i, j in pairs(depicttable) do
	 	if j.rank == 'preferred' then
	 		table.insert(maintopics, preferreddescription(wikidata.getmainid(j), lang))
	 	else 
	 		table.insert(othertopics, normaldescription(wikidata.getmainid(j), lang))
	 	end
	end
	if (#maintopics + #othertopics) == 0 then
		return
	end
	
	local header, maintopicstring, othertopicstring
	if (#maintopics + #othertopics) == 1 then
		header = translate('topic', lang) -- could also use the label of P180 be that sounds slightly awkward
	else
		header = translate('topics', lang)
	end
	local maintopicstring = linguistic.conj(maintopics, lang, '<br />')
	if #othertopics > 0 then
		othertopicstring = linguistic.conj(othertopics, lang, 'comma') 
	end
	if maintopicstring and othertopicstring then -- make the normal values smaller if there are preferred ones
		othertopicsstring = '<small>' .. othertopicstring .. '</small>'
	end
	
	return linguistic.conj({header, maintopicstring, othertopicstring}, lang, '<br />') 
end

local function buildtitle(item, lang) -- todo: choose title by source, formatting by language, translation for foreign language titles
		if type(title) == 'string' then -- should not hapen if buildtitle is a local function anyhow
			item = mw.wikibase.getEntityObject(id)
		end
		
		-- title label
		local title = wikidata.formatStatements({entity=item, property='P357', numval=1, lang=lang})
		if not title then
			title = wikidata._getLabel(item, lang)
		end
		if not title then
			title = item.id
		end
		
		-- link
		local link = item.id
		local formattedtitle = '<i>[[' .. link  .. '|' .. title .. ']]</i>'
		return formattedtitle
end

local function buildcreationdate(item, lang)
	return wikidata.formatStatements({entity=item, property='P571', lang=lang})
end

local function buildtechnique(item, lang)
	local list = wikidata.getClaims{entity=item, property='P186'}
	if not list then
		return nil
	end

	local main = {} -- formatted list of techniques
	local support = {}  -- 'on canvas etc.
	
	for i, j in pairs(list) do
		if j.qualifiers and j.qualifiers.P518 and j.qualifiers.P518[1].snaktype == 'value' and j.qualifiers.P518[1].datavalue.value['numeric-id'] then
			table.insert(support, wikidata.formatStatement(j, {lang=lang}))
		else
			table.insert(main, wikidata.formatStatement(j, {lang=lang}))
		end
	end
	local mainstr = linguistic.conj(main, lang)
	local supportstr = linguistic.conj(support, lang)
	if supportstr then
		return langSwitch({
			en = mainstr .. ' on ' .. supportstr,
			fr = mainstr .. ' sur ' .. supportstr,
			}, lang)
	else
		return mainstr
	end
end

local function buildcollection(item, lang)
	return wikidata.formatStatements({entity=item, property='P195', lang=lang}) 
end

local function buildcurrentplace(item, lang)
	return wikidata.formatStatements({entity=item, property='P276', lang=lang})
end

local function buildcurrentplace(item, lang, collection, place)
	if (collection and place) and (collection ~= place) then
		return collection .. '<br />'
		 .. tostring(mw.message.new('wm-license-artwork-current-location'):inLanguage(lang)).. tostring(mw.message.new('colon'):inLanguage(lang))
		 .. place
	end
	return collection or place
end

local function buildaccessionunmber(item, lang) 
	return wikidata.formatStatements({property = 'P217', entity=item, lang=lang})
end

local function buildinscriptions(item, lang)
	return wikidata.formatStatements({entity=item, property = 'P438', lang=lang})
end

local function buildexhibitionhistory(item, lang)
	local exhibits = wikidata.getClaims({item=item, property = 'P608'})
	if not exhibits then 
		return nil
	end 
	for i, j in pairs(exhibits) do if j.mainsnak.snaktype == 'value' then
		local id = wikidata.getmainid(j)
		local exhibit = mw.wikibase.getEntityObject(id)
		local label = buildtitle(exhibit, lang)
		local begin = wikidata.getClaims({entity = exhibit, numval = 1, property = 'P580'})
		if begin and begin[1].mainsnak.snaktype == 'value' then -- messsy should have a dedicated function for doing this
			begin = begin[1].mainsnak.datavalue.value
		else
			begin = nil
		end
		local enddate = wikidata.getClaims({entity = exhibit, numval = 1, property = 'P582'})
		if enddate and enddate[1].mainsnak.snaktype == 'value' then 
			enddate = enddate[1].mainsnak.datavalue.value 
		else 
			enddate = nil
		end
		local exdate
		if begin or enddate then
			exdate = daterange.wikibasedaterange({startpoint = begin, endpoint = enddate}, lang)
		end
		local place = wikidata.formatStatements({entity = exhibit, lang=lang, property = 'P766'})
		local catnum
		if j.qualifiers and j.qualifiers['P528'] then
			if j.qualifiers['P528'][1].snaktype == 'novalue' then 
				catnum = translate('nocatnumber', lang)
			else
				catnum = catnumber(j.qualifiers['P528'][1].datavalue.value, lang)
			end
		end
		exhibits[i] = linguistic.conj({label, place, exdate, catnum}, lang, 'comma')
	end end
	return linguistic.conj(exhibits, lang, '<br />')
end

function p.artworkbox(item, lang) -- text column
	if not lang then
		lang = mw.getCurrentFrame():preprocess('{{int:lang}}')
	end
	local creator = buildcreator(item, lang)
	creator = wikidata.formatClaimList(creator, {lang=lang})
	if creator then
		creator = table.concat(creator, '<br />')
	end
	local title = buildtitle(item, lang)
	local creationdate = buildcreationdate(item, lang)
	local technique = buildtechnique(item, lang)
	local currentplace =  buildcurrentplace(item, lang)
	return linguistic.conj({creator, title, creationdate, technique, currentplace}, lang, '<br />')
end

local function buildlicensebox(license, lang)
	if not license then
		return  translate("missinglicense", lang)
	end
	return mw.getCurrentFrame():expandTemplate{ title = license, args = {} }
end

local function buildfilebox(lang, creators, title, creationdate, collection, photographer, photodate, photodescription, photodate, source, license)
	local newcreators = {}
	if creators then 
		for i, j in pairs(creators) do
		newcreators[i] = wikidata.formatStatement(j, lang)
	end end
	local creatorstr = linguistic.conj(newcreators, lang)
	if photographer then
		photographer = translate('photo', lang) .. colon(lang) .. photographer
	end

	local artworkstring = linguistic.conj({creatorstr, title, creationdate, collection}, lang, 'comma')
	if artworkstring then
		artworkstring = artworkstring .. linguistic.fullstop(lang)
	else
		artworkstring = ''
	end
	
	local filestring = linguistic.conj({photographer, source, filedesc, photodate, source, license}, lang, 'comma')
	if filestring then
		filestring = filestring .. linguistic.fullstop(lang)
	else 
		filestring = ''
	end

	return artworkstring .. filestring
end

local function formatlong(lang, creators, title, creationdate, description, technique, institution, location, accessionnumber, inscriptions, events, depicted, exhibitionhistory)
	--- header (creators, title, dates)
	if creators then for i, j in pairs(creators) do
		local val = wikidata.getmainid(j)
		if utils.isinstance(val, 'Q5') then 
			creators[i] = persondescription.nameanddates(val, lang) -- to tweak
		else
			creators[i] = wikidata.formatStatement(j, {lang=lang})
	end end end
	local creatorstring = linguistic.conj(creators, lang, '<br />')
	local title =  '<big>' .. title ..'</big>'
	local header = linguistic.conj({creatorstring, title, creationdate}, lang, '<br />')
	
	--- mainbox (technique, institution, inv number)
	local currentplace =  buildcurrentplace(item, lang, institution, location)
	local mainbox = linguistic.conj({description, technique, currentplace, accessionnumber}, lang, '<br />') 
	
	-- inscriptions
	if inscriptions then
		inscriptions =   mw.message.newFallbackSequence( "Wm-license-artwork-inscriptions" ):inLanguage(lang):plain() .. colon(lang) .. '<br />' .. inscriptions
	end
	--- historybox
	local historybox
	if events then 
		historybox = translate('history', lang).. colon(lang) .. '<br />' .. events
	end
	--- exhibox
	local exhibox
	if exhibitionhistory then
		exhibox = mw.language.new(lang):ucfirst( wikidata._getLabel('P608', lang)) ..  colon(lang) .. '<br />' .. exhibitionhistory
	end

	--- concat all that
	return linguistic.conj({header, mainbox, inscriptions, depicted, historybox, exhibox}, lang, '<br /><br />')
end

function p.longdescription(item, lang)
	if type(item) == 'string' then
		item = mw.wikibase.getEntityObject(item)
	end
	-- get data about the artwork
	local creators = wikidata.getClaims({item=item, property = 'P170'})
	local title = buildtitle(item, lang)
	local creationdate = buildcreationdate(item, lang)
	local technique =  buildtechnique(item, lang)
	local institution = buildcollection(item, lang)
	local location = buildcurrentplace(item, lang)
	local accessionnumber =  buildaccessionunmber(item, lang) -- todo: match with institution
	local events = require('Module:Timeline')._timeline(item, lang, {property = {'P793'}})
	local inscriptions = buildinscriptions(item, lang)
	local depicted = builddepicted(item, lang)
	local exhibitionhistory = buildexhibitionhistory(item, lang) 
	--format
	return formatlong(lang, creators, title, creationdate, nil, technique, institution, location, accessionnumber, inscriptions, events, depicted, exhibitionhistory)
end

local function commonsdescription(item, lang, args)
	
	local item = mw.wikibase.getEntityObject(item)
	-- get data about the artwork
	local creators = args.artist or wikidata.getClaims({item=item, property = 'P170'})
	local title = args.title or buildtitle(item, lang)
	local creationdate = args.date or buildcreationdate(item, lang)
	local description = args.description
	local technique = args.technique or buildtechnique(item, lang)
	local institution = args.insitution or buildcollection(item, lang)
	local location = args.location  or buildcurrentplace(item, lang)
	local accessionnumber =  args['accession number'] or buildaccessionunmber(item, lang) -- todo: match with institution
	local inscriptions = args.inscriptions or buildinscriptions(item, lang)	
	local events = require('Module:Timeline')._timeline(item, lang, {property = {'P793'}})
	local depicted = builddepicted(item, lang)
	local exhibitionhistory = buildexhibitionhistory(item, lang) 

	-- build boxes about file data
	local photographer, photodate, photodescription, source, license  = args.photographer, args['photo date'], args['photo description'], args.source, args.permission

	local filebox = buildfilebox(lang, creators, title, creationdate, collection, photographer, photodate, photodescription, photodate, source, license  )

	local artworkbox = formatlong(lang, creators, title, creationdate, description, technique, institution, location, accessionnumber, inscriptions, events, depicted, exhibitionhistory)
		 or 'sorry not much to say about this artwork, please add info to [[:d:' .. item.id .. ']] if you can'

	local licensebox = buildlicensebox(license, lang)
	
	return filebox .. '<br /><br />' .. artworkbox..  '<br /><br />' ..licensebox
end

function p.makedescription(frame)
	local lang =  frame.args[lang]
	local item = frame.args[1]
	if not lang or lang == '' then
		lang = frame:preprocess('{{int:lang}}')
	end
	return p.longdescription(item, lang)
end

return p