Module:Titulaires
Apparence
[voir] [modifier] [historique] [purger]
Utilisation
Le module Titulaires est constitué de différentes parties. Ses fonctions sont réutilisées par les modèles {{Titulaires}} et {{Liste des dirigeants successifs}}.
- local wikidataProperties permet de choisir la fonction voulue : P6 (« chef ou cheffe de l'exécutif »), P35 (« chef d'État »), P1037 (« dirigé par »), P488 (« président ou présidente »), P169 (« directeur général ou directrice générale ») ou P3320 (« membre du conseil d'administration ») ;
- local charterMap indique que Q3266850 (« commune ») est une commune ;
La documentation de ce module est générée par le modèle {{Documentation module}}.
Elle est incluse depuis sa sous-page de documentation. Veuillez placer les catégories sur cette page-là.
Les éditeurs peuvent travailler dans le bac à sable (modifier).
Voir les statistiques d'appel depuis le wikicode sur l'outil wstat et les appels depuis d'autres modules.
local countryData = require 'Module:Country data'
local duration = require 'Module:Durée'
local formatDate = require 'Module:Date complexe'
local langue = require 'Module:Langue'
local linguistic = require 'Module:Linguistique'
local roman = require 'Module:Romain'
local tools = require 'Module:Outils'
local wikidata = require 'Module:Wikidata'
local yn = require 'Module:Yesno'
local p = {}
local wikidataProperties = {
['chef d\'État'] = {
fonction = 'P1906',
plurielFonction = 'Chefs d\'État',
listeIndividus = 'P35',
},
['chef de l\'exécutif'] = {
fonction = 'P1313',
plurielFonction = 'Chefs de l\'exécutif',
listeIndividus = 'P6',
},
['dirigeant'] = {
plurielFonction = 'Dirigeants',
listeIndividus = 'P1037'
},
['président'] = {
plurielFonction = 'Présidents',
listeIndividus = 'P488'
},
['secrétaire général'] = {
plurielFonction = 'Secrétaires généraux',
listeIndividus = 'P3975'
},
['directeur général'] = {
plurielFonction = 'Directeurs généraux',
listeIndividus = 'P169'
},
['membre du conseil d\'administration'] = {
plurielFonction = 'Membres du conseil d\'administration',
listeIndividus = 'P3320'
},
['commandant'] = {
plurielFonction = 'Commandants',
listeIndividus = 'P4791'
}
}
local charterToClass = {
['localité'] = 'localites',
['commune'] = 'communes',
['canton'] = 'cantons',
['arrondissement'] = 'arrondissements',
['intercommunalité'] = 'intercommunalites',
['département'] = 'departements',
['région'] = 'regions'
}
-- Association élément → Charte
local charterMap = {
Q3455524 = 'région',
Q6465 = 'département',
Q702842 = 'arrondissement',
Q2311958 = 'canton',
Q3266850 = 'commune', -- commune
Q15284 = 'commune', -- municipalité
Q515 = 'commune' -- ville
}
local function getArgumentValue(params, argName)
return tools.validTextArg(params.args, argName,
argName .. ' ' .. params.leaderType)
end
local function getBooleanArgumentValue(params, argName, default)
return yn(getArgumentValue(params, argName) or '', default)
end
local function getCharterRecursively(entity, maxDepth) -- fonction permettant d'aller chercher la charte
local candidates = {entity}
for i = 0, maxDepth do
local newCandidates = {}
if i == 0 then
recursiveProperty = 'P31' -- nature de l'élément
else
recursiveProperty = 'P279' -- sous-classe
end
for _, candidate in pairs(candidates) do
local superclasses = wikidata.getIds(candidate, {removedupes = true,
property = recursiveProperty, rank = 'valid'})
newCandidates = wikidata.addNewValues(newCandidates, superclasses)
end
if #newCandidates == 0 then
return nil
end
for _, candidate in pairs(newCandidates) do
local charte = charterMap[candidate]
if charte then
return charte
end
end
candidates = newCandidates
end
end
local function getOfficesRecursively(entity, officeProp, maxDepth)
if not officeProp then
return nil
end
local candidates = {entity}
for i = 0, maxDepth do
local officesTable = {}
for _, candidate in pairs(candidates) do
local claims = wikidata.getClaims({entity = candidate,
property = officeProp, rank = 'valid'})
officesTable = wikidata.addNewValues(officesTable, claims)
end
if #officesTable > 0 then
stringTable, _ = wikidata.stringTable({
claims = wikidata.chronoSort(officesTable), removedupes = true,
--[[Si une page correspondant à la fonction n'est pas disponible
sur Wikipédia en français, essayer d'obtenir la page de liste
correspondante (e.g. Liste des maires de Paris) et, si non
disponible, la superclasse
]]
defaultlinkquery = {property = {'P2354', 'P279'}},
--Afficher les dates de validité de la fonction
showdate = true
})
local formattedOffices = linguistic.conj(stringTable, 'or')
if i == 0 then
return formattedOffices
else
local locationName = wikidata.getLabel(entity)
return formattedOffices .. ' ' .. linguistic.of(locationName)
end
end
local newCandidates = {}
if i == 0 then
recursiveProperty = 'P31' -- nature de l'élément
else
recursiveProperty = 'P279' -- sous-classe
end
for _, candidate in pairs(candidates) do
local superclasses = wikidata.getIds(candidate, {removedupes = true,
property = recursiveProperty, rank = 'valid'})
newCandidates = wikidata.addNewValues(newCandidates, superclasses)
end
if #newCandidates == 0 then
return nil
end
candidates = newCandidates
end
end
local function getDefaultTitle(entity, wProps)
local formattedOffices = getOfficesRecursively(entity, wProps.fonction, 5)
if formattedOffices then
return 'Individus ayant assumé la fonction de ' .. formattedOffices .. '.'
end
local locationName = wikidata.getLabel(entity)
if locationName then
return wProps.plurielFonction .. ' ' .. linguistic.of(locationName) .. '.'
end
return wProps.plurielFonction .. '.'
end
local function getDeterminationMethod(statement) -- fonction permettant d'aller chercher la méthode de détermination, comme une élection
local params = {conjtype = 'new line', removedupes = true,
displayFormat = 'raw'}
return wikidata.getFormattedQualifiers(statement, 'P459', params)
end
local function getEndCause(statement) -- fonction permettant d'aller chercher le motif de fin, comme une mort en cours de mandat ou une démission
local params = {conjtype = 'comma', removedupes = true,
displayFormat = 'raw'}
return wikidata.getFormattedQualifiers(statement, 'P1534', params)
end
local function dateObject(orig)
--[[ transforme un snak en un nouvel objet utilisable par Module:Date complexe
{type = 'dateobject', timestamp = str, era = '+' ou '-', year = number, month = number, day = number, calendar = calendar}
Inspiré de Module:Wikidata
]]--
local newobj = formatDate.splitDate(orig.time, orig.calendarmodel)
newobj.precision = orig.precision
newobj.type = 'dateobject'
return newobj
end
-- établit la variable gender pour l'élément
-- copié depuis Module:Infobox/Fonctions/Personne
local function getGenderedValue(entity, valueF, valueM, valueDefault)
local gender = wikidata.formatStatements{entity = entity, property = 'P21',
displayformat = 'raw'}
if gender == 'Q6581072' or gender == 'Q1052281' or gender == 'Q43445' then
return valueF
elseif gender == 'Q6581097' or gender == 'Q2449503' or gender == 'Q44148' then
return valueM
else
return valueDefault
end
end
local function getDateObjectFromQualif(statement, qualif)
if (not statement.qualifiers) or not (statement.qualifiers[qualif]) then
return nil
end
local v = statement.qualifiers[qualif][1]
if v.snaktype == 'value' then
return dateObject(v.datavalue.value)
end
end
local function getDateObjectFromProperty(entity, property)
-- dateObject
local claim = wikidata.getClaims({entity = entity, property = property,
numval = 1})
if not claim then
return
end
local snak = claim[1].mainsnak
if snak.snaktype == 'value' then
return dateObject(snak.datavalue.value)
end
end
local function getDateWithPrefix(dateObject)
local formattedDate = formatDate.simplestring(dateObject)
local prefix
if dateObject.precision <= 7 then -- siècle, millénaire, ...
prefix = 'au '
elseif dateObject.precison == 8 then -- décennie
prefix = 'dans les '
elseif dateObject.precision <= 10 then -- mois, année, décénnie
prefix = 'en '
else -- jour et moins
prefix = 'le '
end
return prefix .. formattedDate
end
local function getBirthDeathDates(statement)
local entity = wikidata.getMainId(statement)
local dateOfBirth = getDateObjectFromProperty(entity, 'P569')
local dateOfDeath = getDateObjectFromProperty(entity, 'P570')
if dateOfBirth and dateOfDeath then
return formatDate.simplestring(dateOfBirth)
.. ' - '
.. formatDate.simplestring(dateOfDeath)
elseif dateOfBirth then
return getGenderedValue(entity, 'née ', 'né ', 'né(e) ')
.. getDateWithPrefix(dateOfBirth)
elseif dateOfDeath then
return getGenderedValue(entity, 'morte ', 'mort ', 'mort(e) ')
.. getDateWithPrefix(dateOfDeath)
end
end
local langDirCache = {} -- cache pour la direction d'une langue
local function getNameInOtherLanguage(statement, lang)
local entity = wikidata.getMainId(statement)
local label = wikidata.getLabel(entity, lang)
if label then
local dir = langDirCache[lang]
if not dir then
dir = langue.directionLangue({lang})
langDirCache[lang] = dir -- stocker la direction dans le cache
end
return langue.indicationDeLangue({'', lang, texte = label, dir = dir})
end
end
local function getIdentity(statement, params)
local name = wikidata.formatSnak(statement.mainsnak) or ''
if params:yesno('sources', true) then
local references = wikidata.getReferences(statement)
name = name .. (wikidata.sourceStr(references) or '')
end
local showNameInOtherLanguage = params:arg('nom dans la langue')
if showNameInOtherLanguage then
local labelInOtherLanguage = getNameInOtherLanguage(statement,
showNameInOtherLanguage)
if labelInOtherLanguage then
name = name .. '<br />' .. labelInOtherLanguage
end
end
if params:yesno('dates de vie', true) then
local dates = getBirthDeathDates(statement)
if dates then
name = name .. '<br /><small>(' .. dates .. ')</small>'
end
end
return name
end
local function getCitizenship(statement)
local entity = wikidata.getMainId(statement)
return countryData.getNationality({item = entity, mindate = '-',
conjtype = 'new line'})
end
local function getSeriesOrdinal(statement)
local params = {conjtype = 'comma', removedupes = true}
return wikidata.getFormattedQualifiers(statement, 'P1545', params)
end
local function getStartDate(statement)
local dateObj = getDateObjectFromQualif(statement, 'P580')
return formatDate.simplestring(dateObj)
end
local function textWithSortValue(text, sortValue)
if not sortValue then
return text
end
return '<span data-sort-value="' .. sortValue .. '">' .. text .. '</span>'
end
-- Valeur "en cours", avec clé de tri maximale, affichée grâce à un rang privilégié
local currentNode = textWithSortValue('En cours', '999999-12-12')
local function getEndDate(statement, params)
local dateObj = getDateObjectFromQualif(statement, 'P582')
if dateObj then
local endDate = formatDate.simplestring(dateObj)
local endCause = getEndCause(statement)
if endCause then
return endDate .. '<br /><small>(' .. endCause .. ')</small>'
end
return endDate
elseif params.latest and statement.rank == 'preferred' then
return currentNode
end
end
local function getDuration(statement, params)
local startDate = getDateObjectFromQualif(statement, 'P580')
if not startDate then
return
end
local precision = startDate.precision
local endDate = getDateObjectFromQualif(statement, 'P582')
if endDate then
precision = math.min(precision, endDate.precision)
elseif not (params.latest and statement.rank == 'preferred') then
-- Mandat non considéré comme "en cours"
return
else
endDate = {}
end
if precision < 9 then
-- No year
return
end
if precision < 11 then
-- No day
startDate.day = nil
endDate.day = nil
if precision < 10 then
-- No month
startDate.month = nil
endDate.month = nil
end
end
return duration._duree({startDate.day, startDate.month, startDate.year,
endDate.day, endDate.month, endDate.year})
end
local function getPartyColoredSquare(qid) -- Permet d'aller chercher la couleur politique d'un parti ; celle-ci est définie dans son élément via la propriété P465 couleur triplet hexadécimal sRGB
local partyColor = wikidata.formatStatements{entity = qid,
property = 'P465', numval = 1}
if partyColor then
return mw.getCurrentFrame():expandTemplate{
title = 'Carré couleur', args = {'#' .. partyColor }
}
end
end
local function getShortNameIfAvailable(qid)
local shortName = wikidata.formatStatements{entity = qid,
property = 'P1813', numval = 1, isinlang = 'locallang'}
return shortName or mw.wikibase.label(qid)
end
local function getPartyOrParliamentaryGroup(statement, prop, params, abbreviate)
local qualifiers = wikidata.getQualifiers(statement, prop)
if not qualifiers then
return nil
end
local showPoliticalColors = params:yesno('couleur politique', false)
for i, qualifier in ipairs(qualifiers) do
local partyFormatParams = {}
if abbreviate then
partyFormatParams.labelformat = getShortNameIfAvailable
end
local formattedSnak = wikidata.formatSnak(qualifier, partyFormatParams)
if showPoliticalColors then
local qid = wikidata.getId(qualifier)
local coloredSquare = getPartyColoredSquare(qid)
if coloredSquare then
formattedSnak = coloredSquare .. ' ' .. formattedSnak
local partyName = wikidata.getLabel(qid)
formattedSnak = textWithSortValue(formattedSnak, partyName)
end
end
qualifiers[i] = formattedSnak
end
return linguistic.conj(qualifiers, 'new line')
end
local function getParty(statement, params)
return getPartyOrParliamentaryGroup(statement, 'P102', params,
params:yesno('abréger étiquette', false))
end
local function getParliamentaryGroup(statement, params)
return getPartyOrParliamentaryGroup(statement, 'P4100', params,
params:yesno('abréger groupe parlementaire', false))
end
local function getPositionsHeld(statement)
local params = {conjtype = 'new line', removedupes = true}
return wikidata.getFormattedQualifiers(statement, 'P39', params)
end
local function getParliamentaryOrdinal(entity)
-- Recherche de nature de l'élément = Q15238777
local legislativeTermInfos = wikidata.getClaims({entity = entity,
property = 'P31', rank = 'valid', targetvalue = 'Q15238777',
})
if not legislativeTermInfos then
return nil
end
for _, legislativeTermInfo in ipairs(legislativeTermInfos) do
if legislativeTermInfo.qualifiers then
local parliamentaryTermOf = legislativeTermInfo.qualifiers['P642']
local seriesOrdinal = legislativeTermInfo.qualifiers['P1545']
if parliamentaryTermOf and #parliamentaryTermOf == 1
and seriesOrdinal and #seriesOrdinal == 1
and seriesOrdinal[1].snaktype == 'value' then
return tonumber(seriesOrdinal[1].datavalue.value)
end
end
end
end
local function getParliamentaryTermLabel(ordinal)
local exposant
if ordinal == 1 then exposant = 're' else exposant = 'e' end
return (roman.toRoman(ordinal) or ordinal)
.. '<sup>' .. exposant .. '</sup>'
end
local function getParliamentaryTerm(statement, params)
if not statement.qualifiers then
return nil
end
local qualifiers = statement.qualifiers['P2937'] -- Législature
if not qualifiers or #qualifiers == 0 then
return nil
end
local ordinalLabels = {}
local smallestOrdinal
if params:yesno('abréger législature', false) then
local countOrdinals = 0
for _, qualifier in ipairs(qualifiers) do
local qualifierId = wikidata.getId(qualifier)
local ordinal = getParliamentaryOrdinal(qualifierId)
if ordinal then
local qualifierLabel = mw.wikibase.label(qualifierId) or ''
local termLabel = '<span title="' .. qualifierLabel .. '">'
.. getParliamentaryTermLabel(ordinal)
.. '</span>'
ordinalLabels[qualifierId] = termLabel
qualifier._parliamentOrdinal = ordinal
countOrdinals = countOrdinals + 1
end
end
if countOrdinals == #qualifiers then
-- Autant d'ordinaux que de qualifiers, on peut trier
table.sort(qualifiers,
function(a, b)
return a._parliamentOrdinal < b._parliamentOrdinal
end)
smallestOrdinal = qualifiers[1]._parliamentOrdinal
end
end
local args = {defaultlinkquery = 'P2354',
labelformat = function(qid)
return ordinalLabels[qid] or mw.wikibase.label(qid)
end
}
for i, qualifier in ipairs(qualifiers) do
qualifiers[i] = wikidata.formatSnak(qualifier, args)
end
return textWithSortValue(linguistic.conj(qualifiers, 'and'),
smallestOrdinal)
end
local function getPicture(statement)
local entity = wikidata.getMainId(statement)
local claims = wikidata.getClaims({entity = entity, rank = 'best',
property = 'P18', numval = 1})
local caption
local mediaName
if claims then
local claim = claims[1]
mediaName = wikidata.formatStatement(claim)
caption = wikidata.getFormattedQualifiers(claim, {'P2096'},
{isinlang = 'fr', conjtype = 'comma'})
if not caption or caption == '' then
local personName = mw.wikibase.label(entity)
if personName then
caption = personName
local pictureDate = wikidata.getFormattedQualifiers(claim,
{'P585'}, {conjtype = 'comma'})
if pictureDate then
caption = caption .. ', ' .. pictureDate .. '.'
end
end
end
else
-- Pas de portrait
mediaName = getGenderedValue(entity,
'Gray - replace this image female.svg',
'Gray - replace this image male.svg',
'Sin foto.svg')
local personName = mw.wikibase.label(entity)
if personName then
caption = 'Pas de portrait sous licence libre disponible pour '
.. personName .. '.'
else
caption = 'Pas de portrait sous licence libre disponible.'
end
end
return '[[Fichier:' .. mediaName .. '|border|80px|' .. caption .. ']]'
end
local numero = '<abbr class="abbr" title="Numéro">N<sup>o</sup></abbr>'
local cellKindProperties = {
['ordre'] = {fn = getSeriesOrdinal, dataSortType = 'unsortable',
columnName = numero},
['portrait'] = {fn = getPicture, dataSortType = 'unsortable'},
['identité'] = {fn = getIdentity, dataSortType = 'text'},
['nationalité'] = {fn = getCitizenship, dataSortType = 'text'},
['début'] = {fn = getStartDate},
['fin'] = {fn = getEndDate},
['durée'] = {fn = getDuration},
['étiquette'] = {fn = getParty, dataSortType = 'text'},
['groupe parlementaire'] = {fn = getParliamentaryGroup, dataSortType = 'text'},
['fonction'] = {fn = getPositionsHeld, dataSortType = 'text'},
['législature'] = {fn = getParliamentaryTerm, dataSortType = 'number'},
['méthode de détermination'] = {fn = getDeterminationMethod,
dataSortType = 'text', columnName = 'Déterminé par'},
}
local multiColumns = {
['période'] = {'début', 'fin'}
}
local orderedColumnsWithDefaultVisibility = {
{name = 'ordre', defaultVisibility = false},
{name = 'portrait', defaultVisibility = false},
{name = 'identité', defaultVisibility = 'always'},
{name = 'nationalité', defaultVisibility = false},
{name = 'période', defaultVisibility = true},
{name = 'durée', defaultVisibility = true},
{name = 'étiquette', defaultVisibility = false},
{name = 'groupe parlementaire', defaultVisibility = false},
{name = 'fonction', defaultVisibility = false},
{name = 'législature', defaultVisibility = false},
{name = 'méthode de détermination', defaultVisibility = false},
}
local function getColumnsAndCellKinds(params)
local headerColumns = {}
local cellKinds = {}
for _, column in ipairs(orderedColumnsWithDefaultVisibility) do
local shouldShowColumn = column.defaultVisibility == 'always'
or params:yesno(column.name, column.defaultVisibility)
if shouldShowColumn then
table.insert(headerColumns, column.name)
local columnCellKinds = multiColumns[column.name] or {column.name}
for _, cellKind in ipairs(columnCellKinds) do
table.insert(cellKinds, cellKind)
end
end
end
return headerColumns, cellKinds
end
local function getHeaderBaseCell(column)
columnProperties = cellKindProperties[column] or {}
local columnName = columnProperties.columnName or linguistic.ucfirst(column)
local baseCell = mw.html.create('th')
:attr('scope', 'col')
:wikitext(columnName)
local dataSortType = cellKindProperties[column]
and cellKindProperties[column].dataSortType
if dataSortType then
if dataSortType == 'unsortable' then
baseCell = baseCell:addClass('unsortable')
else
baseCell = baseCell:attr('data-sort-type', dataSortType)
end
end
return baseCell
end
local function getHeader(columns)
local headerFirstRow = mw.html.create('tr')
local headerSecondRow = mw.html.create('tr')
for _, column in pairs(columns) do
local cell = getHeaderBaseCell(column)
local subcolumns = multiColumns[column]
if subcolumns then
cell = cell:attr('colspan', #subcolumns)
for _, subColum in ipairs(subcolumns) do
headerSecondRow:node(getHeaderBaseCell(subColum):done())
end
else
cell = cell:attr('rowspan', 2)
end
headerFirstRow = headerFirstRow:node(cell:done())
end
return headerFirstRow:done(), headerSecondRow:done()
end
local function getLeaderRow(cellKinds, statement, params)
local row = mw.html.create('tr'):css({['vertical-align'] = 'top'})
for _, cellKind in pairs(cellKinds) do
local success, result = pcall(cellKindProperties[cellKind].fn, statement, params)
if not success then
result = tostring(mw.html.create('span')
:wikitext('Erreur')
:attr('title', result)
:css('font-style', 'italic')
:css('font-size', 'small')
:done())
end
row = row:node(mw.html.create('td')
:wikitext(result or '')
:done())
end
return row:done()
end
local function getTitle(params, entity, wProps)
local title = params:arg('titre') or getDefaultTitle(entity, wProps)
-- Bouton d'édition wikidata
title = wikidata.addLinkBack(title, entity, wProps.listeIndividus)
-- Formattage du titre
return mw.html.create('caption')
:wikitext(title)
:done()
end
local function peopleList(entity, args, wPropsList, charter)
if not entity then
return mw.html.create('span')
:addClass('error')
:wikitext('Pas d\'entité Wikidata pour l\'élément.')
:done()
end
local params = {entity = entity, args = args}
params.arg = getArgumentValue
params.yesno = getBooleanArgumentValue
local maxWidth = args['largeur maximale'] or '900px'
local tables = {}
for leaderType, wProps in pairs(wPropsList) do
local elus = wikidata.getClaims({entity = entity,
property = wProps.listeIndividus, sorttype = 'chronological',
rank = 'valid'})
if elus then
params.leaderType = leaderType
local title = getTitle(params, entity, wProps)
local headerColumns, cellKinds = getColumnsAndCellKinds(params)
local firstHeadRow, secondHeaderRow = getHeader(headerColumns)
local tab = mw.html.create('table')
:addClass('wikitable')
:addClass('centre')
:addClass('sortable')
:addClass(charterToClass[charter])
:css('max-width', maxWidth) -- largeur maximale du tableau
:node(title) -- titre
:node(firstHeadRow) -- première ligne
:node(secondHeaderRow) -- deuxième ligne
params.latest = 0
-- Ajout des lignes des dirigeants
for i, statement in ipairs(elus) do
if i == #elus then
params.latest = 1
end
local leaderRow = getLeaderRow(cellKinds, statement, params)
tab = tab:node(leaderRow)
end
table.insert(tables, tostring(tab:done()))
end
end
return table.concat(tables, '\n')
end
function p.listeDesDirigeantsSuccessifs(frame)
local args = tools.extractArgs(frame)
-- Entité Wikidata
local entity = wikidata.getEntity(args.wikidata)
local wPropsList
if args.types then
wPropsList = {}
for leaderType in mw.text.gsplit(args.types, '%s*,%s*') do
wPropsList[leaderType] = wikidataProperties[leaderType]
end
else
wPropsList = wikidataProperties
end
-- Charte
local charter = args.charte or getCharterRecursively(entity, 2)
return peopleList(entity, args, wPropsList, charter)
end
return p