Module:DroitsAuteur

La documentation pour ce module peut être créée à Module:DroitsAuteur/Documentation

--[[  
Le module DroitsAuteur sert à construire un lien à la page Auteur:   
suivi d’un icone indiquant si l’œuvre visée est du D.P.

3 icones sont disponibles : 
1) Domaine public, 
2) Sujet à droits d’auteur 
3) Cas incertain qui requiert une confirmation en utilisant le parmètre nommé droits=XX

EXEMPLE :
Appel à partir d’une page Wikisource ou d’un module :
{{#invoke:DroitsAuteur|DA|Floris Delattre|F. DELATTRE}}]]
--Réponse obtenue :
--[[Auteur:Floris Delattre|F. DELATTRE]]--&nbsp[[Fichier:PD-icon.svg|10px
--|Élément non soumis aux droits d’auteur.|link=Aide:Droit d’auteur]] 

--test : =p.DroitsAuteur("Floris Delattre", "F. DELATTRE")

p = {}

-- La lecture dans Wikidata s’effectue avec l’aide du code empruntée du
-- module Auteur2. Merci à l’auteur de ce module.

function computeCenturyFromYear(year)
	-- Return the correpsonding century for the given year
	if year >= 0 then
		return math.ceil(year / 100)
	else
		return -math.ceil(-year / 100)
	end
end

function getTextForCentury(century, withHtml)
	-- Return a roman ordinal of century appended with a trailing text precising
	-- if the date is before of after the calendar reference point.
	local romanNumbers1 = {'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'}
	local romanNumbers2 = {'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'}

	local text = romanNumbers2[math.floor(math.abs(century) / 10) + 1] .. romanNumbers1[math.floor(math.abs(century) % 10) + 1]
	if withHtml then
		text = text .. '<sup>e</sup>'
	else
		text = text .. 'e'
	end
	if century > 0 then
		return text .. ' siècle'
	else
		return text .. ' siècle av. J.-C.'
	end
end

function getTextForYear(year)
	local text = math.abs(year)
	if year < 0 then
		text = text .. ' av. J.-C.'
	end
	return text
end

function getDateFromArgs(args, field, fieldUpper)
	local struct = {
		year = nil,
		century = nil,
		text = nil,
		precision = 0
	}

	--extract year or century
	local date = args['annee' .. fieldUpper]
	if date == nil then
		date = args[field]
	end
	if tonumber(date) ~= nil then
		struct.year = tonumber(date)
		if struct.year == 0 then
			struct.text = errorMessage("Le calendrier grégorien ne possède pas d’année 0 !")
			return struct
		end
		struct.century = computeCenturyFromYear(struct.year)
		struct.precision = 9
	elseif args['siecle' .. fieldUpper] ~= nil then
		struct.century = tonumber(args['siecle' .. fieldUpper])
		struct.precision = 7
	end

	--build text
	if struct.year ~= nil then
		struct.text = getTextForYear(struct.year)
	elseif struct.century ~= nil then
		struct.text = getTextForCentury(struct.century, true)
	else
		struct.text = date
	end
	if args['text' .. fieldUpper] ~= nil then
		struct.precision = 0 --we don't know anything
		struct.text = args['text' .. fieldUpper] .. ' ' .. struct.text
	end
	if args['incertitude' .. fieldUpper] ~= nil and struct.text ~= nil then
		struct.precision = 0 --we don't know anything
		struct.text = args['incertitude' .. fieldUpper] .. ' ' .. struct.text
	end

	return struct
end
function getDateFromTimeStatements(statements, field)
	if #statements == 0 then
		return {
			precision = 0
		}
	end

	local time = nil
	for _, statement in pairs(statements) do
		local newTime = getDateFromTimeStatement(statement, field)
		if time == nil then
			time = newTime
		elseif time.year ~= newTime.year then --années contradictoires
			mw.addWarning('Plusieurs années de ' .. field .. ' possibles sur Wikidata. Une manière simple de résoudre se problème est de mettre la date à afficher au rang "préféré".')
		end
	end

	if time == nil then
		return {
			precision = 0
		}
	end

	return time
end

function parseWbTime(value)
	local _,_, year = string.find(value.time, '([%+%-]%d%d%d+)%-')
	year = tonumber(year)
	
	return {
		year = year,
		century = computeCenturyFromYear(year),
		text = nil,
		precision = value.precision
	}
end

function getDateFromTimeStatement(statement, field)
	local struct = {
		year = nil,
		century = nil,
		text = nil,
		precision = 0
	}
	local snak = statement.mainsnak
	if snak.snaktype == 'novalue' then
		return struct
	end
	if snak.snaktype == 'somevalue' then
		struct.text = '??'
		return struct
	end
	
	struct = parseWbTime(snak.datavalue.value)
	local prefix = ''
	if struct.precision == 8 then
		prefix = 'vers '
	end

	--Extract circa
	if statement.qualifiers ~= nil and statement.qualifiers.P1480 ~= nil then
		for _,qualifier in pairs(statement.qualifiers.P1480) do
			if qualifier.datavalue.value.id == 'Q5727902' then
				prefix = 'circa '
				struct.precision = 8 --TODO: hacky
			end
		end
	end
	--Use before and after if precision <= century
	if statement.qualifiers ~= nil and struct.precision <= 7 then
--		if statement.qualifiers.P1319 ~= nil then
--			for _,qualifier in pairs(statement.qualifiers.P1319) do
--				struct = parseWbTime(qualifier.datavalue.value)
--				prefix = 'après '
				--struct.precision = 8 --TODO: hacky
--			end
--		elseif statement.qualifiers.P1326 ~= nil then
		if statement.qualifiers.P1326 ~= nil then
			for _,qualifier in pairs(statement.qualifiers.P1326) do
				struct = parseWbTime(qualifier.datavalue.value)
				prefix = 'avant '
				--struct.precision = 8 --TODO: hacky
			end
--		elseif statement.qualifiers.P1317 ~= nil then
--			for _,qualifier in pairs(statement.qualifiers.P1317) do
--				struct = parseWbTime(qualifier.datavalue.value)
--				prefix = 'floruit '
--				struct.precision = 8 --TODO: hacky
--			end
		end
	end

	--Create text
	if struct.precision >= 9 then
		struct.text = prefix .. getTextForYear(struct.year)
	elseif struct.precision == 8 then
		struct.text = prefix .. getTextForYear(struct.year)
	elseif struct.precision == 7 then
		struct.text = prefix .. getTextForCentury(struct.century, true)
	else
		struct.text = errorMessage('La date de ' .. field .. ' a une précision trop faible sur Wikidata')
	end
	
	return struct
end

function formatDates(naissance, deces, class)
	if naissance.text == nil and deces.text == nil then
		return ''
	end

	local text = '('
	if naissance.precision >= 9 then
		local annotation = 'class="bday" itemprop="birthDate"'
		if class ~= "Q5" and class ~= nil then
			annotation = 'itemprop="foundingDate'
		end
		text = text .. '<time datetime="' .. naissance.year .. '" ' .. annotation .. '>' .. naissance.text .. '</time> '
	elseif naissance.text ~= nil then
		text = text .. naissance.text .. ' '
	end
	text = text .. '–'
	if deces.precision >= 9 then
		local annotation = 'class="dday" itemprop="deathDate"'
		if class ~= "Q5" and class ~= nil then
			annotation = 'itemprop="dissolutionDate'
		end
		text = text .. ' <time datetime="' .. deces.year .. '" ' .. annotation .. '>' .. deces.text .. '</time>'
	elseif deces.text ~= nil then
		text = text .. ' ' .. deces.text
	end
	return text .. ')'
end

function qidForProperty(item, property)
	local statements = item:getBestStatements(property)
	if statements[1] ~= nil and statements[1].mainsnak.datavalue ~= nil then
		return statements[1].mainsnak.datavalue.value.id
	end
	return nil
end

function searchKey(key)
	-- normally the key does not contain any diacritic but it's a common misuse
	-- of the clef = so handle at least the most usual diacritics, note than
	-- prenom can be empty
	local nom, prenom = mw.ustring.match(key, '^([A-ZÉÈÀÇa-zéèàç-]*)[,]?[ ]*(.*)$')
	return prenom .. ' ' .. 'intitle:' .. nom
end

function p.getDroitsPA(nomAuteur)
	local titre = mw.title.new( nomAuteur, 'Auteur' )
	local contenu = ''
	local fragment = ''
	if titre ~= nil then 
		contenu = titre:getContent()
		if contenu ~= nil then
			fragment = mw.ustring.match(contenu, 'droits(.-)|')
		end
	end
	return fragment
end

function p.DA(frame)
	local args = frame.args
	local szCode = ''
	--if args then return frame:getParent().args['wikdita'] end
	if args[1] == nil and args['wikdita'] == nil then
		args = frame:getParent().args
	end
	return p.DroitsAuteur(args)
end

function p.DroitsAuteur(args)
	local da = '&nbsp;[[Fichier:Red copyright.svg|10px'
		    .. '|Élément soumis aux droits d’auteur.|link=Aide:Droit d’auteur]]'
	local dp = '&nbsp;[[Fichier:PD-icon.svg|10px'
		    .. '|Élément non soumis aux droits d’auteur.|link=Aide:Droit d’auteur]]'
	local dpa = '&nbsp;[[File:PDmaybe-icon.svg|10px'
		    .. '|Élément à préciser quant aux droits d’auteur.|link=Aide:Droit d’auteur]]'
	local ddef = 70 --droits par défaut
	local id
	local nomAuteur
	local droitsC
	
	if args[1] and args[1] ~= '' then nomAuteur = args[1] end
	if args[2] and args[2] ~= '' then libele = args[2] end
	if args[3] and args[3] ~= '' then droitsC = args[3] end
	if args['wikidata'] and args['wikidata'] ~= '' then id = args['wikidata'] end
	
	if id ~= nil then
		nomAuteur = mw.wikibase.getLabelWithLang(id)
		if nomAuteur == nil then
			return "Auteur non trouvé dans wikidata " .. "[[Catégorie:Auteur inexistant]]"
		end
		else if args[1] == nil then
			return "Mauvaise utilisation du modèle Creator " .. "[[Catégorie:Auteur inexistant]]"
		end
	end

	if libele == nil then libele = nomAuteur end

	
	if not id then id = mw.wikibase.getEntityIdForTitle('Auteur:' .. nomAuteur) end
	if id == nil then return 'Auteur inexistant' end
	local item = mw.wikibase.getEntity(id)
	local naissanceWikidata = getDateFromTimeStatements(item:getBestStatements('P569'), 'naissance')
	if naissanceWikidata.precision == 0 and naissanceWikidata.text == nil then
		naissanceWikidata = getDateFromTimeStatements(item:getBestStatements('P571'), 'création')
	end
	local decesWikidata = getDateFromTimeStatements(item:getBestStatements('P570'), 'deces')
	if naissanceWikidata.precision == 0 and decesWikidata.text == nil then -- on utilise la date de dissolution
		decesWikidata = getDateFromTimeStatements(item:getBestStatements('P576'), 'dissolution')
	end
	
	local str = '[[Auteur:' .. nomAuteur .. '|' .. libele .. ']]'
	
	if decesWikidata.year == nil then
		return str .. dpa    -- pas de date de décès dans Wikidata
	end
-- Si précision = 7 (siècle) on utilisa la dernière année du siècle
	if decesWikidata.precision == 7 then
		decesWikidata.year = decesWikidata.year + 49
	end 
-- Si précision = 8 (décadee) on utilisa la dernière année de la décade
	if decesWikidata.precision == 8 then
		decesWikidata.year = decesWikidata.year + 5
	end
	--On traite d’abord les droits confirmés avec le modèle DA droits = XX
	if droitsC ~= nil and droitsC ~= ''  then
		if tonumber(os.date("%Y")) <= decesWikidata.year + droitsC then
			return str .. da
		else
			return str .. dp
		end		
	end
	
	--Puis les droits présumés selon l’inscription au modèle Auteur
	local drPageAuteur = p.getDroitsPA(nomAuteur)

	-- Si 50 ans 
	if drPageAuteur and drPageAuteur ~= '' then
		--if true then return 'oui' end
		if mw.ustring.match(drPageAuteur, '50') then
			if tonumber(os.date("%Y")) <= decesWikidata.year + 50 then
				if decesWikidata.precision < 9 then
					return str .. dpa
				else
					return str .. da
				end
			else 
				return str .. dp
			end

		end
	-- Auteur mort pour la France droits à confimer entre 80 et 95 ans
		if mw.ustring.match(drPageAuteur, 'mpf') or 
			mw.ustring.match(drPageAuteur, '100') then
			if tonumber(os.date("%Y")) <= decesWikidata.year + 80 then
				return str .. da
			elseif tonumber(os.date("%Y")) <= decesWikidata.year + 95 then
				return str .. dpa
			else return dp 
			end	
			end
	-- Respect du modèle Auteur si droits y sont définis à plus de 70 ans
		drPageAuteur = tonumber(mw.text.split(drPageAuteur,'=')[2])
		if drPageAuteur ~= nil and drPageAuteur > 70 then
			ddef = drPageAuteur
		end
	
	end
	-- Tous les cas sans ambiguité passent ici 70 ans et +
	if tonumber(os.date("%Y")) <= decesWikidata.year + ddef then
		if decesWikidata.precision < 9 then
			return str .. dpa
		else
			return str .. da
		end
	else
		return str .. dp
	end
	return str
end

return p