Aller au contenu

Module:Wikidata/Références

Un livre de Wikilivres.

Fonctions exportables :

  • citeitem(id, page, dateconsult) – formate au format Wikitexte, en utilisant les modèles de citation standard si possible, la référence.

Test :

  • Paul E. Black, Polylogarithmic, (article d'encyclopédie), National Institute of Standards and Technology (d), , lire en ligneVoir et modifier les données sur Wikidata
  • William Trevor, The Story of Lucy Gault, (œuvre littéraire), Viking Press, Voir et modifier les données sur Wikidata
  • J. R. R. Tolkien, The Lord of the Rings, (suite romanesque), George Allen & Unwin, Royaume-Uni, Voir et modifier les données sur Wikidata, J. R. R. Tolkien, Christopher Tolkien, The Children of Húrin, (œuvre littéraire), HarperCollins et Houghton Mifflin Harcourt, Voir et modifier les données sur Wikidata
  • J. R. R. Tolkien, Christopher Tolkien, The Return of the Shadow, (œuvre écrite), HarperCollins, Londres, Voir et modifier les données sur Wikidata
  • (en) William Mickey Haynes (dir.), CRC Handbook of Chemistry and Physics, Boca Raton, CRC Press, , 92e éd. (ISBN 978-1-4398-5511-9), p. 122Voir et modifier les données sur Wikidata
  • Kathinka Dittrich van Weringh (préface) et Frédéric Blin (dir.), Les bibliothèques en Europe : Organisation, projets, perspectives, Paris, Cercle de la Librairie, , 340  p. (ISBN 978-2-7654-1368-4, ISSN 0184-0886, notice BnF no FRBNF43560909)Voir et modifier les données sur Wikidata
  • « Vitrine du logiciel », Théoric, Rennes (d), Éditions Soracom (d), no 3,‎ , p. 54-55 (ISSN 0762-6711, OCLC 474139660, notice BnF no FRBNF34392888)Voir et modifier les données sur Wikidata
  • Robert Mowat, Études philologiques sur les inscriptions gallo-romaines de Rennes, Paris et Rennes, , 27  p. (notice BnF no FRBNF30990597, lire sur Wikisource)Voir et modifier les données sur Wikidata

Sandbox:

  • troisième bac à sable de Wikidata, (entité interne de Wikidata)Voir et modifier les données sur Wikidata

Modèle:Projet Scribunto

local reference = {}

local wd = require 'Module:Wikidata'
local refType = mw.loadData 'Module:Wikidata/Références/Types'

local linguistic = require 'Module:Linguistique'
local cite = require 'Module:Biblio'
local langcodes = mw.loadData 'Module:Dictionnaire Wikidata/Codes langue'

local function concatTables(t1,t2)
	local results = {}
	for _,e in pairs(t1) do
    	table.insert(results, e)
    end
    for _,e in pairs(t2) do
    	table.insert(results, e)
    end
    return results
end

local function getStringStatementValues(entity, propertyId)
	local statements = entity:getBestStatements(propertyId)
	for i, statement in pairs(statements) do
		statements[i] = statement.mainsnak.datavalue.value
	end
	return statements
end

local function getStringStatementValue(entity, propertyId)
	local statements = getStringStatementValues(entity, propertyId)
	if #statements > 0 then
		return statements[1]
	else
		return nil
	end
end

local function getDirectItemLang(workentity, property)
	local itemlangs = wd.getClaims{entity = workentity, property = property}
	if itemlangs ~= nil then
		return langcodes[wd.getNumericId(itemlangs[1].mainsnak)]
	end
end

local function hasRole(statement, roleId)
	return statement.qualifiers and (
		statement.qualifiers['P518'] and wd.getId(statement.qualifiers['P518'][1]) == roleId
		or statement.qualifiers['P794'] and wd.getId(statement.qualifiers['P794'][1]) == roleId
	)
end	

local currentPageTitle = mw.title.getCurrentTitle().prefixedText

local function buildAuthorLink(statement)
	local author_label = nil
	local author_link = nil
	-- we extract the link and the label of the author if it is an entity
	if statement.mainsnak.snaktype == 'value' and statement.mainsnak.datatype == 'wikibase-item' then
		local author_id = statement.mainsnak.datavalue.value.id
		author_label = mw.wikibase.getLabel(author_id)
		author_link = mw.wikibase.getSitelink(author_id)
	end
	-- we use stated in to retrive the proper author label by setting it in statement.mainsnak
	if statement.qualifiers and statement.qualifiers['P1932'] then
		statement.mainsnak = statement.qualifiers['P1932'][1]
	end
	-- and then by getting the label from its value (supports also P2093)
	if statement.mainsnak.snaktype == 'value' and statement.mainsnak.datatype == 'string' then
		author_label = statement.mainsnak.datavalue.value
	end
	
	if author_link ~= nil and author_link ~= currentPageTitle then
		return '[[' ..author_link .. '|' .. author_label .. ']]'
	else
		return author_label
	end
end

local function remove_same_isbn(isbns)
	-- input a table of isbns
	-- return a table of ibns without duplicate
	-- asked in https://fr.wikipedia.org/wiki/Discussion_mod%C3%A8le:Bibliographie#ISBN-10_et_ISBN-13
	local References = require( 'Module:Biblio/Références' )
	local result = {}
	for _, isbn1 in ipairs(isbns) do
		local same = false
		for index_isbn2, isbn2 in ipairs(result) do
			if  References.same_isbn(isbn1, isbn2) then
				if isbn2:gsub( '[ -]', '' ):len() == 13 then
					table.remove(result, index_isbn2)
					table.insert(result, isbn1)
				end
				same = true
				break
			end
		end
		if not same then
			table.insert(result, isbn1)
		end
	end
	return result
end

function reference.citeitem(entityId, options)
	if not entityId then
		return nil
	end
	local entity = wd.getEntity(entityId)
	if not entity then
		return 'invalid entity id'
	end
	if type( options ) ~= 'table' then
		options = {}
	end
	
	--work entity if it exists
	local workEntity = nil
	local workClaims = wd.getClaims{entity = entity, property = 'P629'} -- P629 : édition de
	if workClaims ~= nil then
		workEntity = wd.getEntity(wd.getMainId(workClaims[1]))
	end
	local journalEntity = nil
	local journalClaims = wd.getClaims{entity = entity, property = 'P1433'}
	if journalClaims ~= nil then
		journalEntity = wd.getEntity(wd.getMainId(journalClaims[1]))
	end

	local translator = wd.formatStatements{entity = entity, property = 'P655', defaultlink = '-'}
	local illustrator = wd.formatStatements{entity = entity, property = 'P110', defaultlink = '-'}
	local preface = wd.formatStatements{entity = entity, property = 'P2679', defaultlink = '-'}
	local postface = wd.formatStatements{entity = entity, property = 'P2680', defaultlink = '-'}
	local photographe = ''
	local authors = {}
	local are_director = {}
	local responsability = {}
	
	local author_statements = concatTables(entity:getBestStatements('P50'), entity:getBestStatements('P2093'))
	if next(author_statements) == nil and workEntity ~= nil then --Fallback to work
		author_statements = concatTables(workEntity:getBestStatements('P50'), workEntity:getBestStatements('P2093'))
	end
	for _, statement in pairs(author_statements) do
		local position = #authors + 1
		if statement.qualifiers and statement.qualifiers['P1545'] then
			position = tonumber(statement.qualifiers['P1545'][1].datavalue.value)
		end
		
		authors[position] = buildAuthorLink(statement)
		are_director[position] = ''
	
		--qualifier pour la responsabilité
		if statement.qualifiers and statement.qualifiers['P518'] then
			responsability[position] = wd.formatSnak(statement.qualifiers['P518'][1], {defaultlink = '-'})
		else
			responsability[position] = ''
		end
	end
	for _, statement in pairs(entity:getBestStatements('P98')) do
		table.insert(authors, buildAuthorLink(statement))
		table.insert(are_director, 'y')
		table.insert(responsability, '')
	end
	
	for _, statement in pairs(entity:getBestStatements('P767')) do
		if hasRole(statement, 'Q670787') or hasRole(statement, 'Q19839393') then --préface/préfacier
			preface = buildAuthorLink(statement)
		elseif hasRole(statement, 'Q7234272') then --postface
			postface = buildAuthorLink(statement)
		elseif hasRole(statement, 'Q33231') or hasRole(statement, 'Q125191') then --photographe/photographie
			photographe = buildAuthorLink(statement)
		end
	end
	
	local isbns = getStringStatementValues(entity, 'P212')
	for _, isbn in pairs(getStringStatementValues(entity, 'P957')) do
		table.insert(isbns, isbn)
	end
	local issns = {}
	if journalEntity then
		issns = getStringStatementValues(journalEntity, 'P236')
	end
	if #issns == 0 then
		issns = getStringStatementValues(entity, 'P236')
	end
	local oclc = getStringStatementValue(entity, 'P243')
	local bnf = getStringStatementValue(entity, 'P268')
	local lccn = getStringStatementValue(entity, 'P1144')
	local dnb = getStringStatementValue(entity, 'P1292')
	local doi = getStringStatementValue(entity, 'P356')
	local pmid = getStringStatementValue(entity, 'P698')
	local jstor = getStringStatementValue(entity, 'P888')
	local bibcode = getStringStatementValue(entity, 'P1300')
	local arxiv = getStringStatementValue(entity, 'P818')
	local pmcid = getStringStatementValue(entity, 'P932')
	
	local ednumber = wd.formatStatements{entity = entity, property = 'P393'}
	local publisher = wd.formatStatements{entity = entity, property = 'P123', defaultlink = '-'}
	local journal = wd.formatStatements{entity = entity , property = 'P1433', defaultlink = '-'}
	--TODO fix local journalnumber = wd.formatStatements{entity = entity, property = 'P433'}
	--TODO fix local volume = wd.formatStatements{entity = entity, property = 'P478'}

	local publishdate = wd.formatStatements{entity = entity, property = 'P577', linktopic = '-'}
	local publishplace = wd.formatStatements{entity = entity, property = 'P291', defaultlink = '-'}

	--if no publisher, publication date or place, oclc or bnf: look for them in the item stored in P1433, misnamed here as  "journalEntity"
	if (not publisher) and journalEntity then
		publisher = wd.formatStatements{entity = journalEntity, property = "P123", defaultlink = "P577"}
	end
	if (not publishdate) and journalEntity then
		publishdate = wd.formatStatements{entity = journalEntity, property = "P577", linktopic = "P577"}
	end
	if (not publishplace) and journalEntity then
		publishplace = wd.formatStatements{entity = journalEntity, property = "P291", defaultlink = "P577"}
	end
	if (not oclc) and journalEntity then
		oclc = wd.formatStatements{entity = journalEntity, property = "P243", defaultlink = "P577"}
	end
	if (not bnf) and journalEntity then
		bnf = wd.formatStatements{entity = journalEntity, property = "P268", defaultlink = "P577"}
	end

	local pagenum = wd.formatStatements{entity = entity, property = 'P1104'}
	if pagenum then
		pagenum = pagenum:gsub(' +p%.', '') -- on supprime l'unité p.
	end
	local title = wd.formatStatements{entity = entity, property = 'P1476', numval = 1 } or wd.getLabel(entity)
	local titlelink = wd.siteLink(entity)
	local subtitle = wd.formatStatements{entity = entity, property = 'P1680'}
	local url = getStringStatementValue(entity, 'P854') or getStringStatementValue(entity, 'P953')
	local wikisource = entity:getSitelink('frwikisource')
	if wikisource ~= nil and url ~= nil and url:find('%.wikisource%.org') then
		url = nil -- we make sure to not have two links to Wikisource
	end
	local language = getDirectItemLang(entity, 'P407')
	if not language and journalEntity then
		language = getDirectItemLang(journalEntity, 'P407')
	end
	local originalLanguage = getDirectItemLang(entity, 'P364') --TODO: be clever? or getDirectItemLang(workEntity, 'P407') or getDirectItemLang(workEntity, 'P364')
	if not language or language == originalLanguage then
		originalLanguage = nil -- We are actually not sure if it has been translated from this language
	end
	local originalTitle = nil
	if workEntity and originalLanguage then
		originalTitle = wd.formatStatements{entity = workEntity, property = 'P1476', numval = 1 } or workEntity:getLabel(originalLanguage)
	end
	local page = getStringStatementValue(entity, 'P304')
	local numero = getStringStatementValue(entity, 'P433')
	local volume = getStringStatementValue(entity, 'P478')

	-- choose relevant cite type
	local entitytype = wd.formatStatements{property = 'P31', entity = entity, numval = 1, displayformat = 'raw'}
	local funtype
		
		
	-- calcul du rendu du titre de l'ouvrage, éventuellement avec un lien vers l'article de l'ouvrage

	-- pas de lien à générer si on est sur la page de l'ouvrage ou si l'élément cité est une édition de cet ouvrage
	if not ( wd.isPageOfQId(entityId) or 
	   workEntity and wd.isPageOfQId(wd.entityId(workEntity)) )
	then
		if not titlelink and workEntity then
			-- si pas de lien, on peut essayer de voir si c'est l'édition de quelque chose d'autre
			titlelink = wd.siteLink(workEntity)
		end
		if title and titlelink then
			title = '[[' .. titlelink .. '|' .. title .. ']]'
		end
	end

	-- calcul du modèle à utiliser pour rendre l'élémént
	
	if (entitytype == 'Q3331189') then --book edition
		funtype = cite.ouvrage
		
		-- TODO : gérer l'édition et l'élément de l'oeuvre. 
		
	elseif refType.isOuvrage[entitytype] then -- ouvrage sans édition connue ?
		
		-- TODO : gérer le cas ou un ouvrage est cité mais que Wikidata en connait des éditions.
		-- TODO : refuser ce genre d'items ?
		
		funtype = cite.ouvrage
		
	elseif refType.isArticle[entitytype] then -- article
		funtype = cite.article
	else -- default: output a very simple display
		local parameters = authors
		if title then 
			 table.insert(parameters, '<i>' .. title .. '</i>')
		end
		if entitytype and wd.getLabel(entitytype) then
			table.insert(parameters, ' (' .. wd.getLabel(entitytype) .. ')')
		end
		if publisher then
			table.insert(parameters, publisher)
		end
		if publishplace then
			table.insert(parameters, publishplace)
		end
		if publishdate then
			table.insert(parameters, publishdate)
		end
		if url then
			table.insert (parameters, mw.getCurrentFrame():expandTemplate{title="lire en ligne",args={url=url}})
		end
		if options['page'] then
			table.insert(parameters, 'p.' .. options['page'])
		end
		if options['accessdate'] then
			table.insert(parameters, 'consulté le ' .. options['accessdate'])
		end
		parameters[#parameters] = wd.addLinkBack(parameters[#parameters], entity, "P31")
		return linguistic.conj(parameters, 'comma')
	end

	
	local parameters = {
		['traducteur'] = translator,
		['illustrateur'] = illustrator,
		['préface'] = preface,
		['postface'] = postface,
		['photographe'] = photographe,
		['titre'] = title,
		['sous-titre'] = subtitle,
		--['volume'] = volume,
		['date'] = publishdate,
		['lieu'] = publishplace,
		['périodique'] = journal,
		--['numéro'] = journalnumber,
		["numéro d'édition"] = ednumber,
		['éditeur'] = publisher,
		['pages totales'] = pagenum,
		['lire en ligne'] = url,
		['wikisource'] = wikisource,
		['oclc'] = oclc,
		['bnf'] = bnf,
		['lccn'] = lccn,
		['dnb'] = dnb,
		['doi'] = doi,
		['pmid'] = pmid,
		['jstor'] = jstor,
		['bibcode'] = bibcode,
		['arxiv'] = arxiv,
		['pmcid'] = pmcid,
		['langue'] = language,
		['langue originale'] = originalLanguage,
		['titre original'] = originalTitle,
		['page'] = page,
		['numéro'] = numero,
		['volume'] = volume,
		['plume'] = options['plume']
	}
	
	isbns = remove_same_isbn(isbns)
	for i, isbn in pairs(isbns) do
		parameters['isbn' .. i] = isbn
	end
	
	for i, issn in pairs(issns) do
		parameters['issn' .. i] = issn
	end
	
	-- try to find if there is an author set in options
	local setAuthors = true
	for i=1, 15 do
		if options['auteur' .. i]  or options['directeur' .. i] or options['responsabilité' .. i] then
			setAuthors = false
		end
	end

	if setAuthors then
		for i, author in pairs(authors) do
			parameters['auteur' .. i] = author
			parameters['directeur' .. i] = are_director[i]
			parameters['responsabilité' .. i] = responsability[i]
		end
	end
	
	for parameter, value in pairs(options) do
		if value == '-' then
			parameters[parameter] = ''
		else
			parameters[parameter] = value
		end
	end
	local val = funtype(parameters)

	if val then
		return wd.addRefAnchor(wd.addLinkBack(val, entity), wd.entityId(entity))
	end
	
	return wd.formatError()
end

-- pour tester
function reference.citeItem(frame)
	local args = frame:getParent().args
	return reference.citeitem(args[1], args)
end


--used to test the duplicate isbn functions, use in the console like this
-- p.test()
reference.test = function()
	test_same_isbn()
	test_remove_same_isbn()
end

return reference