Module:Infobox : Différence entre versions

De Lagny-sur-Marne Wiki
Aller à : navigation, rechercher
m
(répare bug dans la gestion de la taille, active l'option "wikidata" pour utiliser un autre élément Wikidata que celui lié à l'article)
Ligne 19 : Ligne 19 :
 
-- modules importés
 
-- modules importés
 
local wikidata = require "Module:Interface Wikidata".fromLua
 
local wikidata = require "Module:Interface Wikidata".fromLua
local defaultstyle = require('Module:Infobox/Style')
+
local defaultstyle = require "Module:Infobox/Style"
local mapmod = require('Module:Carte')
+
local mapmod = require "Module:Carte"
  
 
local i18n = {
 
local i18n = {
Ligne 231 : Ligne 231 :
 
end
 
end
  
local numsize = mw.ustring.gsub(size, 'x.*', '')
+
-- Vérifie que les images ne sont pas > 280 px
numsize = numsize:gsub('px', '')
+
local numsize = size:gsub('px', '')
 +
numsize = mw.ustring.gsub(numsize, 'x.*', '')
 
numsize = tonumber(numsize)
 
numsize = tonumber(numsize)
 
if type(numsize) ~= 'number' or numsize > 280 then
 
if type(numsize) ~= 'number' or numsize > 280 then
Ligne 574 : Ligne 575 :
 
end
 
end
 
localdata.templatename = templatename or modulename
 
localdata.templatename = templatename or modulename
-- guess "rank" of the infobox
+
 
 +
-- load wikidata item as a global variable:
 +
if localdata.wikidata == '-' then
 +
item = nil
 +
else
 +
item = wikidata.getEntity(localdata.wikidata)
 +
end
 +
 +
-- assign rank to the infobox, "secondary" means special formatting like no displaytitle for coordinates
 
local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc.
 
local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc.
 
if page.namespace ~= 0 then
 
if page.namespace ~= 0 then
 
infoboxrank = 'secondary'
 
infoboxrank = 'secondary'
 +
end
 +
-- if infobox is linked to another item: rank = secondary
 +
if item then
 +
local itemlink = mw.wikibase.sitelink(item.id)
 +
local pagetitle = mw.title.getCurrentTitle().text
 +
if (itemlink or '') ~= pagetitle then
 +
infoboxrank = 'secondary'
 +
end
 
end
 
end
 
localdata.infoboxrank = infoboxrank
 
localdata.infoboxrank = infoboxrank
  
-- load wikidata item as a global variable:
 
if localdata.wikidata == 'non' then
 
item = nil
 
elseif (not localdata.wikidata) or (localdata.wikidata == '') then
 
item = mw.wikibase.getEntityObject()
 
else
 
item = nil -- topic of the infobox corresponds to another Wikidata item, should eventually be fetched through arbitrary access
 
localdata.infoboxrank = 'secondary'
 
end
 
 
 
-- load infobox module page
 
-- load infobox module page
 
moduledata = require('Module:Infobox/' .. modulename)
 
moduledata = require('Module:Infobox/' .. modulename)

Version du 28 août 2015 à 08:36

La documentation pour ce module peut être créée à Module:Infobox/doc

local p = {}

-- variables globales alimentées par les paramètres utilisés
item = nil -- l'élément Wikidata lié
moduledata = nil -- la sous-page de module:Infobox demandée
localdata = {}-- données concernant les paramètres passés au modèle
maincolor = '#E1E1E1'
page = { -- données concernant la page où est affichée l'infobox
	name = mw.title.getCurrentTitle().prefixedText,
	namespace =  mw.title.getCurrentTitle().namespace
}

-- l'objet principal à retournerp
local infobox = mw.html.create('div')

-- objes secondaires à retourner
local maintenance = '' -- chaîne retournfoée avec le module : cats de maintenance
local externaltext = '' -- par exemple coordonnées en titre
-- modules importés
local wikidata = require "Module:Interface Wikidata".fromLua
local defaultstyle = require "Module:Infobox/Style"
local mapmod = require "Module:Carte"

local i18n = {
	['see doc'] = 'Documentation du modèle',
	['edit'] = 'modifier',
	['edit code'] = 'modifier le code',
	['edit item'] = 'modifier Wikidata',
	['tracking cat'] = "Page utilisant des données de Wikidata",
	['invalid block type'] = "Bloc de données invalide dans le module d'infobox",
	['default cat'] = "Maintenance des infobox",
}

local function addwikidatacat(prop)
	maintenance = maintenance .. '[[Category:' .. i18n['tracking cat'] .. '/' .. string.upper(prop) .. ']]'
end

local function expandquery(query)
	local value, number -- valeur à retourner, nombre de valeurs pour accorder le libellé
	if not query.entity then
		query.entity = item
	end
	if not query.conjtype then
		query.conjtype = 'comma'
	end
	local claims = wikidata.getClaims(query)
		if (not claims) then
		return nil
	end
	return wikidata.formatAndCat(query), #claims -- pour l'accord au pluriel
end

local function getWikidataValue(params, wikidataparam)
	-- Récupère la valeur Wikidata pour la valeur, soit dans le paramètre "wikidata" soit dans le praramètre "property"
	if not item then
		return nil
	end
	local value, number
	
	if not wikidataparam then -- par défaut la valeur wikidata est dans le paramètre "wikidata" mais dans les structures composées comme "title", il y a plusieurs paramètres wikidata
		wikidataparam = 'wikidata'
	end

	if params[wikidataparam] then
		if type(params[wikidataparam]) == 'function' then
			return params[wikidataparam](item)
		elseif type(params[wikidataparam]) == 'table' then
			return expandquery(params[wikidataparam])
		else
			return params[wikidataparam]
		end
	end
end

local function getvalue(val, params)
	if type(val) == 'string' then
		return localdata[val]
	elseif type(val) == 'function' then
		return val(localdata, item, params)
	elseif type(val) == 'table' then
		for i, j in pairs(val) do -- si plusieurs paramètres possibles (legacy de vieux code), prendre le preimeir non bide
			if localdata[j] then
				return localdata[j]
			end
		end
	end
end

local function addmaintenancecat(cat, sortkey)
	if page.namespace ~= 0 then
		return ''
	end
	if cat then
		maintenance = maintenance .. '[[Category:' .. cat .. '|' .. (sortkey or page.name) .. ']]'
	end
end

function p.buildtitle(params)
	local text = getvalue(params.value, params) or params.textdefaultvalue or  getWikidataValue(params) or mw.title.getCurrentTitle().text
	local subtext = getvalue(params.subtitle) or  getWikidataValue(params, 'wikidatasubtitle') or params.subtitledefaultvalue
	if subtext and (subtext ~= text) then
		text = text .. '<br /><small>' .. subtext .. '</small>'
	end
	local icon = params.icon or ''
	if icon ~= '' and not params.large then
		icon = 'icon ' .. icon
	end
	local class = 'entete ' .. icon
	
	-- overwrites with those provided in the module
	local style = {}
	if maincolor then
		style['background-color'] = maincolor
	end
	if params.style then
		for i, j in pairs(params.style) do
			style[i] = j
		end
	end
	local title = mw.html.create('div')
		:addClass(class)
		:css(style)
		:tag('div')
			:wikitext(text)
		:allDone()
	return title
end

function p.buildnavbox(params)
	local class = "overflow nav " .. (params.class or '')
	local style = params.style or {['border-width'] = '1px'}
	if not style['border-color'] then
		style['border-color'] = maincolor
	end
	local previousval = localdata[params.previousparameter]	or getWikidataValue(params, 'previouswikidata')
	if not previousval and params['previousproperty'] then
		previousval = wikidata.formatAndCat{entity = item, property = params['previousproperty']}
	end
	local nextval = localdata[params.nextparameter] or getWikidataValue(params, 'nextwikidata')
	if not nextval and params['nextproperty'] then
		nextval = wikidata.formatAndCat{entity = item, property = params['nextproperty']}
	end
	local navbox =
	mw.html.create('p')
		:addClass(class)
		:css(style)
		:tag('span')
			:addClass('prev_bloc')
			:wikitext(previousval)
			:done()
		:tag('span')
			:addClass('next_bloc')
			:wikitext(nextval)
			:done()
		:done()
		return navbox
end

function p.buildimages(params)
	local images = {}
	local size, link, caption
	if type(params.imageparameters) == 'string' then
		params.imageparameters = {params.imageparameters}
	end
	if not params.imageparameters then -- s'il n'y a pa de paramètre image, continuer, peut-être y-a-t-il une image par défaut définie dans le module d'infobox
		params.imageparameters = {}
	end
	for j, k in ipairs(params.imageparameters) do
		table.insert(images, localdata[k])
	end
	
	-- Images de Wikidata
	if #images == 0 and item then
		if params.property then
			images = wikidata.getClaims{item= item, property = params.property} or {}
			if #images > 0 then
				addwikidatacat(params.property)
			end
		end
		if params.wikidata then
			images = params.wikidata()
			if type(images) == 'string' then
				return images
			end -- c'est probablement une erreur dans la requête => afficher le message
		end
	end
	if type(images[1]) == 'table' then
		for i, j in pairs(images) do
			if j.mainsnak.snaktype ~= 'value' then
				return
			end
			if i > (params.numval) then
				images[i] = nil
			else
				images[i] = j.mainsnak.datavalue.value
			end
		end
	end

	-- Images par défaut
	local isdefault = false
	if #images == 0 then
		if params.maintenancecat then
			local maintenancecat = getvalue(params.maintenancecat, params)
			addmaintenancecat(maintenancecat, params.sortkey)
		end
		if params.defaultimages then
			images = params.defaultimages
			if type(images) == 'string' then
				images = {images}
			end
		end
		size, caption, link = params.defaultimagesize, params.defaultimagecaption, params.defaultimagelink
	end
	if #images == 0 then
		return nil
	end
	
	size = size or getvalue(params.sizeparameter) or params.defaultsize or '280x400px'
	link = link or getvalue(params.linkparameter) or params.defaultlink
	caption = caption or getvalue(params.captionparameter) or params.defaultcaption or ''

	if type(size) == 'function' then
		size = size(localdata)
	end
	if type(link) == 'function' then
		link = link()
	end
	if type(caption) == 'function' then
		caption = caption(localdata)
	end

	-- Vérifie que les images ne sont pas > 280 px
	local numsize = size:gsub('px', '')
	numsize = mw.ustring.gsub(numsize, 'x.*', '')
	numsize = tonumber(numsize)
	if type(numsize) ~= 'number' or numsize > 280 then
		addmaintenancecat("taille d'image invalide")
	end
	if link then
		link = '|link=' .. link
	else
		link = ''
	end
	local style = params.style or {padding ='2px 0',}

	-- Partie image

	local imagesString = ''
	for i,image in pairs(images) do
		if image == '-' then
			return
		end
		imagesString = imagesString ..  '[[Fichier:' .. image .. link .. '|frameless|' .. size
		if #images == 1 then
			imagesString = imagesString .. '|center'
		end
		if image.upright then
			imagesString = imagesString .. '|upright=' .. image.upright
		else
			imagesString = imagesString .. '|upright=' .. ( 1 / #images )
		end
		imagesString = imagesString .. ']]'
	end

	local image = mw.html.create('div')
		:addClass("images")
		:css(style)
		:wikitext(imagesString)

	-- Partie légende
	local captionobj = mw.html.create('p')
	if caption then
		captionobj
			:wikitext(caption)
			:css(params.style or {})
			:addClass("legend")
			:done()
	end
	
	-- séparateur
	local separator
	if params.separator then
		local separatorStyle = params['separator style'] or {}
		separatorStyle.height = separatorStyle.height or '2px'
		separatorStyle['background-color'] = separatorStyle['background-color'] or maincolor
		separator = mw.html.create('hr')
		separator:css( separatorStyle )
	end
	return mw.html.create('div'):node(image):node(captionobj):node(separator):done()
end

function p.buildtext(params)
	local class = params.class or ''
	local style = defaultstyle['boldline']
	if params.style then
		for i, j in pairs(params.style) do
			style[i] = j
		end
	end
	local text = getvalue(params.value, params) or getWikidataValue(params) or params.defaultvalue
	if text == '-' then
		return
	end
	if not text then
		addmaintenancecat(params.maintenancecat, params.sortkey)
		return nil
	end
	local formattedtext = mw.html.create('p')
		:addClass(class)
		:css(style)
		:wikitext(text)
		:done()
	return formattedtext
end

function p.buildrow(params)
	local class = params.class or ''
	local style = params.style or {}
	local value, number =  getvalue(params.value, params)
	if not value then
		value, number =  getWikidataValue(params, 'wikidata')
	end
	if (not value) and (params.property) then
		value, number = expandquery({property = params.property})  -- the property key takes a string value,  that would not work well using the wikidata key 
	end
	if not value then
		value = params.defaultvalue
	end
	if value == '-' then
		return nil
	end
	if not number then
		number = 0 -- == indéfini
	end
	if not value then
		if params.maintenancecat then
			local maintenancecat = getvalue(params.maintenancecat, params)
			addmaintenancecat(maintenancecat, params.sortkey)
		end
		return nil
	end

	local label = params.label
	if number > 1 and (params.plurallabel) then
		label = params.plurallabel
	elseif number == 1 and (params.singularlabel) then
		label = params.singularlabel
	end
	if type(label) == 'function' then
			label = label(localdata, item)
	end

	-- format
	local formattedvalue = mw.html.create('div')
		:wikitext('\n' .. value) -- Le '\n' est requis lorsque value est une liste commençant par '*' ou '#'
		
	if (params.hidden == true)then
		formattedvalue
			:attr({class="NavContent", style="display: none; text-align: left;"})
		formattedvalue = mw.html.create('div')
			:attr({class="NavFrame", title="[Afficher]/[Masquer]", style="border: none; padding: 0;"})
			:node(formattedvalue)
	end
	formattedvalue =  mw.html.create('td')
			:node(formattedvalue)
			:allDone()
	
	local formattedlabel
	if label then
		formattedlabel = mw.html.create('th')
			:attr('scope', 'row')
			:wikitext(label)
			:done()
	end
	local row = mw.html.create('tr')
		:addClass(class)
		:css(style)
		:node(formattedlabel)
		:node(formattedvalue)
		:done()
	
	return row
end

function p.buildtable(params)
	local tab = mw.html.create('table'):css(params.style or {})
	local title
	if params.title then
		local text
		if type(params.title) == 'string' then -- raccourci moche mais pratique : n'utiliser qu'une chaîne pour le titre
			text = params.title
			params.title = {}
		else
			text = getvalue(title.value) or error('no value provided for this title')
		end
		local titlestyle = params.title.style or {['text-align'] = 'center', color = '000000'}
		if not titlestyle['background-color'] then
			titlestyle['background-color']  = maincolor
		end
		local colspan = params.title.colspan or '2'
		title = mw.html.create('caption')
			:attr({colspan = 2})
			:css(titlestyle)
			:wikitext(text)
			:done()
	end
	local rows = {} -- does not add the rows directly to tab: check if some rows are non empty beoforehand so that we do not add a title if there are no data to show
	
	for k, l in pairs(params.rows) do
		if type(l) == 'table' and l.type == 'multi' then -- when a single function is used for return several rows
			table.remove(params.rows, k)
			local count = 0
			for m, n in pairs(l.rows) do
				table.insert(params.rows, k + count, n)
				count = count + 1
			end
			l = params.rows[k]
		end

		if type(l) == 'function' then --accepte les fonctions qui retournent des tables
			l = l(localdata, item)
		end
		if type(l) == 'nil' then
			--ne rien faire (quand la valeur est originellemenet une fonctin elle peut retourner nil)
		elseif type(l) ~= 'table' then
			return error('les lignes d\'infobox ("rows") doivent être des tables, est ' .. type(l))
		else
			local row = p.buildblock(l)
			table.insert(rows, row)
		end
	end
	if #rows > 0 then
		if title then
			tab:node(title)
		end
		for i, j in pairs (rows) do
			tab:node(j)
		end
		tab:allDone()
		return tab
	else
		return nil
	end
end

function p.buildinvalidblock(args)
	addmaintenancecat(defaultcat)
	local text = ''
	if type(args) ~= 'table' then
		text = "Les blocs d'infobox doivent être des tables"
	else
		text = i18n["invalid block type"] .. ' : ' .. (args.type or '??')
	end
	return text
end

function p.buildmap(params)
	local maplist = getvalue(params.maps)
	local pointimage = params.pointimage
	local maptype = params.maptype -- choisit le type de carte le plus approprié (relief, administratif, etc.)	
	if type(maplist) == 'function' then
		maplist = maplist(localdata, item)
	end
	local width = tonumber(params.width) or 280
	if width > 280 then
		addmaintenancecat("Erreur d'Infobox/Image trop grande")
		return 'image trop grande, la largeur doit être inférieure ou égale à 280px'
	end
	local latitude, longitude
	if type(params.latitude) == 'function' then
		latitude, longitude = params.latitude(localdata, item), params.longitude(localdata, item)
	else
		latitude, longitude = localdata[params.latitude], localdata[params.longitude]
	end
	if (not latitude or not longitude) and item and params.wikidata then
		if not type(params.wikidata) == 'function' then
			return error('valeur wikidata incorrecte pour la géolocalisation')
		end
		local val = params.wikidata(item, query)
		if not val then
			return nil
		end
		if (not type(val) == 'table')  then
			return error("mauvaise requête pour les coordonnées de géolocalisation")
		end
		val = val[1]
		if val.mainsnak.snaktype == 'value' then
			latitude, longitude = val.mainsnak.datavalue.value.latitude, val.mainsnak.datavalue.value.longitude
		end
	end
	if not latitude or not longitude then
		return nil
	end
	local newparams = {maplist = maplist, pointimage = pointimage, width = width, item = item, latitude = latitude, longitude = longitude}
	if params.params and type(params.params) == 'table' then -- paramètres additionnels
		for i, j in pairs(params.params) do
			newparams[i] = j
		end
	end
	return mapmod.multimap(newparams)
end

function p.buildfooter(params)
	if not params then
		params = {}
	end
	
	local class = 'navbar noprint ' .. (params.class or '')
	local style = params.style or {}
	style['border-top'] = style['border-top'] or '1px solid ' .. maincolor
	
	local backlinkstr = '[' .. tostring( mw.uri.fullUrl( page.name, '&veaction=edit&section=0' ) ) .. ' ' .. i18n['edit'] .. ']'
		.. ' - [' .. tostring( mw.uri.fullUrl( page.name, '&action=edit&section=0' ) ) .. ' ' .. i18n['edit code'] .. ']'

	local itemlinkstr
	if item then
		itemlinkstr = '[[d:' .. item.id .. '|' .. i18n['edit item'] .. ']]'
	end
	local editstr = backlinkstr
	if itemlinkstr then
		editstr = editstr .. ' - ' .. itemlinkstr
	end
	local editlinkspan =  mw.html.create('span')
		:css({['text-align'] = "left"})
		:addClass('plainlinks')
		:wikitext(editstr)
		:done()
	local doclinkstr = '[[Image:Gtk-dialog-info.svg|12px|link=' .. localdata.templatename .. '|' .. i18n['see doc'] .. ']]'
	-- si ce lien ne marche pas toujours, il faut ajouter un variable pour le nom de l'infobox récupéré par le frame
	local doclinkspan = mw.html.create('span')
		:css({['text-align'] = "right"})
		:wikitext(doclinkstr)
		:done()
	
	local footer = mw.html.create('p')
		:addClass(class)
		:css(style)
		:node(editlinkspan)
		:node(doclinkspan)
	return footer
end

function p.buildblock(block)
	if type(block) == 'function' then
		block = block()
	end

	local blocktypes = { -- list of functions for block buildings
		['invalid'] = p.buildinvalidblock,
		['external text'] = p.buildexternaltext,
		['footer'] = p.buildfooter,
		['images'] = p.buildimages,
		['map']= p.buildmap,
		['mixed'] = p.buildrow,
		['navbox'] = p.buildnavbox,
		['table'] = p.buildtable,
		['row'] = p.buildrow,
		['text'] = p.buildtext,
		['title'] = p.buildtitle,
	}
	if type(block) ~= 'table' or (not block.type) or (not blocktypes[block.type]) then
		return blocktypes['invalid'](block)
	end
	return blocktypes[block.type](block) 
end

function p._build(modulename, params, templatename)

	-- fill-up global variable localdata using params
	for i, j in pairs(params) do
		if j and mw.text.trim(j) ~= '' then -- empty parameters are ignored
			localdata[i] = j
		end
	end
	localdata.templatename = templatename or modulename

	-- load wikidata item as a global variable:
	if localdata.wikidata == '-' then
		item = nil
	else
		item = wikidata.getEntity(localdata.wikidata)
	end
	
	-- assign rank to the infobox, "secondary" means special formatting like no displaytitle for coordinates
	local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc.
	if page.namespace ~= 0 then
		infoboxrank = 'secondary'
	end
	-- if infobox is linked to another item: rank = secondary
	if item then
		local itemlink = mw.wikibase.sitelink(item.id)
		local pagetitle = mw.title.getCurrentTitle().text
		if (itemlink or '') ~= pagetitle then
			infoboxrank = 'secondary'
		end
	end
	localdata.infoboxrank = infoboxrank

	-- load infobox module page
	moduledata = require('Module:Infobox/' .. modulename)
	moduledata.name = modulename
	-- defines main color
	maincolor = localdata['couleur infobox'] or localdata['couleur boîte'] or moduledata.maincolor or maincolor
	if maincolor:match( '^%x%x%x%x%x%x$' ) or maincolor:match( '^%x%x%x$' ) then
		maincolor = '#' .. maincolor
	end
	
	-- class
	local class = 'infobox_v3'
	if moduledata.class then
		class = class .. ' ' .. moduledata.class
	end
	
	-- style
	local style = moduledata.style or {}
	if not style['max-width'] then
		style['max-width'] = '300px'
	end
	
	-- build infobox
	infobox	:addClass(class)
			:css(style)
	for i, j in pairs( moduledata.parts ) do
		infobox:node( p.buildblock(j) )
	end
	infobox	:node(p.buildfooter(moduledata.footer))
			:done()
			
	return tostring(infobox) .. externaltext, maintenance
end

function p.build(frame)
	local name =  frame.args.nom
	local parent = frame:getParent()
	local templatename = parent:getTitle() -- au cas où il soit différent du nom du module
	local params = parent.args
	return p._build(name, params, templatename) 
end

return p