Aller au contenu

« Module:Adresse » : différence entre les versions

De Wreck
Modèle:Infobox>Zolo
erruer de script réparée, prépare à la personnalisation par zone géographique
m 59 versions importées
 
(54 versions intermédiaires par 8 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
local formats = require "Module:Adresse/Formats"
local p = {}
local p = {}
local wikidata = require "Module:Wikidata"
local linguistic = require "Module:Linguistique"
local countrymodule = require "Module:Country data"


local wikidata =require('Module:Wikidata')
local function getCountry(item) -- get country id for formatting
 
local country = wikidata.getIds(item, {property = "P17"})
local areaformatting = {
if (not country) then
-- identifant wikipédia = regex pour le format de l'adresse
-- $number : le numéro de l'immeuble
-- $ street : le nom de la rue
-- questions :
-- utiliser des noms plutôt que des ID wikidata ?
-- si problème de performance, utiliser des fonctions plutôt que des regex ?
Q39 = '$street $number', -- Suisse
Q142 = '$number $street',-- France
default = '$number $street',
}
 
local function formatStreet(streetname, housenumber, area)
local val = areaformatting[area] or areaformatting['default']
val = mw.ustring.gsub(val, '$number', housenumber or '')
val = mw.ustring.gsub(val, '$street', streetname or '')
return val
end
 
function p.formatAddress(streets, postcode, city, formattingarea)
-- streets est une table de {streetname, number, }
-- formatting area est le lieu, normalement plus large que "city" qui détermine le formatage de la rue et du code postal
if (not streets or #streets == 0) and (not postcode) and (not city) then  
return nil
return nil
end
end
 
if #country > 1 then
local addresslines = {} -- lignes à mettre dans l'adresse : rue, codepostal + ville etc.
return nil
if streets then
table.insert(addresslines, mw.text.listToText(streets))
end
if postcode or formattingarea then
table.insert(addresslines, (postcode or '') .. ' ' .. (formattingarea or ''))
end
end
return table.concat(addresslines, '<br />')
return country[1]
end
end


Ligne 47 : Ligne 25 :
table.insert(vals, wikidata.formatSnak(j))
table.insert(vals, wikidata.formatSnak(j))
end
end
return table.concat(vals)
return table.concat(vals, '-')
end
end


local function streetFromClaims(claim) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
local function directionFromClaim(claim, area) -- par exemple rue Sherbrooke Ouest
if not claim.mainsnak.snaktype == 'value' then
if not claim.qualifiers or not claim.qualifiers.P560 then
return nil
return nil
end
end
return wikidata.formatSnak(claim.mainsnak)
local str = ''
for i, snak in pairs(claim.qualifiers.P560) do
local directionlabels = area.directions or formats.default.directions
str = str .. wikidata.formatSnak(snak,  {speciallabels = directionlabels})
end
return str
end
 
local function streetFromClaims(claim) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
return wikidata.formatStatement(claim)
end
 
local function formatStreet(streetname, housenumber, direction, displayformat)
local val = displayformat.streetline or formats.default.streetline
val = mw.ustring.gsub(val, '$number', housenumber or '')
val = mw.ustring.gsub(val, '$street', streetname or '')
val = mw.ustring.gsub(val, '$direction', direction or '')
return val
end
end


local function wikidatastreet(claim , area) --formate des données sur la rue à partir d'une affirmation Wikidata
local function wikidatastreet(claim, area) --formate des données sur la rue à partir d'une affirmation Wikidata
local streetname = streetFromClaims(claim)
local streetname = streetFromClaims(claim, area)
local housenumber =  numberFromClaim(claim)
local housenumber =  numberFromClaim(claim, area)
return formatStreet(streetname, housenumber, area)
local direction = directionFromClaim(claim, area)
return formatStreet(streetname, housenumber, direction, area)
end
end


function p.wikidataAddress(item) -- fprùate l'intégralité d'une adresse à partir des données contenues dans une élément Wikidata
function p.streetAddress(item, area) -- formate la ligne concernant la rue et le numéro de rue
-- essaye la propriété P669 (données de type 'élément'
local streets -- châine contenant le ou les rues et numéros d'immeuble
-- TODO : récupérer la zone géographique pour le formatage
local streetclaims = wikidata.getClaims{item=item, property = 'P669', item=item}
if not area then
local streetstrings = {}
local country = getCountry(item)
local area = wikidata.getClaims({item = item, property = 'P17'}) -- utilise le pays comme approximation pour le format d'adresse à utiliser
if country and formats[country] then
if area and #area > 0 then
area = formats[country]
area = wikidata.getmainid(area[1])
else
area = formats.default
end
end
end
-- essaye de remplir street, en priorité avec P669, type : élément
local streetclaims = wikidata.getClaims{entity = item, property = 'P669'}
if streetclaims then
if streetclaims then
for i, j in pairs(streetclaims) do
for i, j in pairs(streetclaims) do
streetstrings[i] = wikidatastreet(j, area)
streetclaims[i] = wikidatastreet(j, area)
end
streets = mw.text.listToText(streetclaims)
streets = wikidata.formatAndCat{value = streets, entity = item, property = 'P669'}
end
-- sinon : P6375, type : string -- remplace P969
if not streets then
streets = wikidata.formatAndCat{linkback = true, property = 'P6375', entity = item, isinlang = 'fr'}
end
-- sinon : P969, type : string -- propriété obsolète
if not streets then
streets =  wikidata.formatAndCat{linkback = true, property = 'P969', entity = item}
end
return streets
end
 
function p.adminDivList(item, country) -- returns a list of admin divisions matching the criteria defined in Module:Adresse/Formats
country = country or getCountry(item)
local query = {property = 'P131'}
local divs = wikidata.transitiveVals(item, query, 0, 10, country)
local validDivs = {}
-- solution 1: looks for divs of a certain type
local function setValue(targetclasses, depth)
local test = {}
for _, d in pairs(divs) do
for j, divtype in pairs(targetclasses) do
if (divtype == '-') then
if #validDivs > 0 then
divs = wikidata.addVals(divs, query, 0, 1, country)
end
if divs[#divs] == country then
return nil
end
return divs[#divs]
end
if wikidata.isInstance(divtype, d, 3) then
-- restrain list to new value, will be expanded only if needed
divs = {d}
return d
end
end
end
if depth >= 0 then
local num = #divs
divs = wikidata.addVals(divs, query, 0, 10, country)
if #divs > num then return setValue(targetclasses, depth) end
end
end
else
-- sinon,essaye p969: datatype: string
streetclaims =  wikidata.getClaims{property = 'P969', item=item}
if streetclaims then for i, j in pairs(streetclaims) do streetstrings[i] = wikidata.formatStatement(j) end end
end
end
-- code postal
 
local postcode = wikidata.getClaims{property= 'P281', item=item}
-- solution2: looks for divs that are part of a closed list (way more efficient for big items)
if postcode and #postcode > 1 then -- s'il y a plusieurs codes postaux, il y a sans doute plusieurs adresses différentes, c'est difficile de savoir lequel correspond à laquelle
local function findInList(list, depth)
postcode = nil
for i, j in pairs(divs) do
elseif postcode then
for k, l in pairs(list) do
postcode = wikidata.formatStatement(postcode[1])
if j == l then
divs = {l}
return l
end
end
end
if depth >= 0 then
local num = #divs
divs = wikidata.addVals(divs, query, 0, 10, country)
if #divs > num then return findInList(list, depth) end
end
end
end
-- faaut-il essayer d'ajouter la ville par P131 ? Souvent on en veut pas (par exemple en infobox)
local val = p.formatAddress(streetstrings, postcode)
local displayformat = formats[country] or formats.default
if val then return
local maxdepth = 3
val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
if not divs then
return nil
end
 
if displayformat.div1 then
local val = setValue(displayformat.div1, maxdepth)
if val and val ~= validDivs[#validDivs] then
table.insert(validDivs, val)
end
end
 
if displayformat.div2 then
local val = setValue(displayformat.div2, maxdepth)
if val and val ~= validDivs[#validDivs] then
table.insert(validDivs, val)
end
elseif displayformat.div2vals then
local val =  findInList(displayformat.div2vals, 1)
if val and val ~= validDivs[#validDivs] then
table.insert(validDivs, val)
end
end
if displayformat.div3 then
local val = setValue(displayformat.div3, maxdepth)
if val and val ~= validDivs[#validDivs] then
table.insert(validDivs, val)
end
elseif displayformat.div3vals then
local val =  findInList(displayformat.div3vals, 0)
if val and val ~= validDivs[#validDivs] then
table.insert(validDivs, val)
end
end
return validDivs
end
 
function p.cityLine(item, country, divlist, postcode) -- line with list of admin divisions + optional postcode
country = country or getCountry(item)
local postcode = postcode or wikidata.formatStatements{entity = item, property = 'P281'} or ''
if postcode == '-' then -- can be disabled when it is not useful
postcode = ''
end
local divstr = ''
if (not divlist) or (#divlist == 0) then
divlist = p.adminDivList(item, country)
end
if (not divlist) or (#divlist == 0) then
return -- add a maintenance category ?
end
for i, j in pairs(divlist) do
if string.find(j, '^Q[0-9]+$') then
divlist[i] = wikidata.formatEntity(j)
end
end
local divstr = linguistic.conj(divlist, 'comma')
 
local formatting = formats[country] or formats.default
local str = formatting.cityline or formats.default.cityline
str = str:gsub("$postcode", postcode or '')
str = str:gsub("$admindivs", divstr or '')
return str
end
 
function p.fullAddress(item, country, divs, streetstr, divstr, showcountry, postcode)
-- country id used for formatting
country = country or getCountry(item)
local displayformat = formats[country] or formats.default
 
-- line 1 street
local streetline = streetstr or p.streetAddress(item, country)
-- line 2: administrative divisions, postcodes
local cityline = divstr
if not cityline then cityline = p.cityLine(item, country, divs, postcode) end
if (not cityline) or mw.text.trim(cityline) == '' then
cityline = nil
end
 
-- line 3: country
local countryline, success
if (showcountry ~= '-') then
countryline, success = countrymodule.standarddisplay(country)
if not success then
if (type(country) == 'string') and string.find(country, "^Q[0-9]+$") then
countryline = wikidata.formatEntity(country)
else
countryline = country or wikidata.formatStatements{entity = item, property = 'P17'}
end
end
end
local str = linguistic.conj({streetline, cityline, countryline}, '<br />')
if str and (not streetstr) and (not divstr) then -- à peu près
str = str .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
end
local hasstreetline
if streetline then hasstreetline = true else hasstreetline = false end
 
return str, hasstreetline
end
 
function p.wikidataAddress(item, country) -- fonction de transition
local area = formats[country] or formats.default
local val = p.streetAddress(item, area)
if val then
return val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
end
end
end
end
return p
return p

Dernière version du 22 février 2026 à 00:17

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

local formats = require "Module:Adresse/Formats"

local p = {}
local wikidata = require "Module:Wikidata"
local linguistic = require "Module:Linguistique"
local countrymodule = require "Module:Country data"

local function getCountry(item) -- get country id for formatting
	local country = wikidata.getIds(item, {property = "P17"})
	if (not country) then
		return nil
	end
	if #country > 1 then
		return nil
	end
	return country[1] 
end

local function numberFromClaim(claim) -- récupère le numéro de l'immeuble à partir d'un qualificatif P670 d'une affirmation Wikidata
	if not claim.qualifiers or not claim.qualifiers.P670 then
		return nil
	end
	local vals = {}
	for i, j in pairs(claim.qualifiers.P670) do
		table.insert(vals, wikidata.formatSnak(j))
	end
	return table.concat(vals, '-')
end

local function directionFromClaim(claim, area) -- par exemple rue Sherbrooke Ouest
	if not claim.qualifiers or not claim.qualifiers.P560 then
		return nil
	end
	local str = ''
	for i, snak in pairs(claim.qualifiers.P560) do
		local directionlabels = area.directions or formats.default.directions
		str = str .. wikidata.formatSnak(snak,  {speciallabels = directionlabels})
	end
	return str
end

local function streetFromClaims(claim) -- réupère le nom de la rue à partir d'une affirmation P669 Wikidata
	return wikidata.formatStatement(claim)
end

local function formatStreet(streetname, housenumber, direction, displayformat)
	local val = displayformat.streetline or formats.default.streetline
	val = mw.ustring.gsub(val, '$number', housenumber or '')
	val = mw.ustring.gsub(val, '$street', streetname or '')
	val = mw.ustring.gsub(val, '$direction', direction or '')
	return val
end

local function wikidatastreet(claim, area) --formate des données sur la rue à partir d'une affirmation Wikidata
	local streetname = streetFromClaims(claim, area)
	local housenumber =  numberFromClaim(claim, area)
	local direction = directionFromClaim(claim, area)
	return formatStreet(streetname, housenumber, direction, area)
end

function p.streetAddress(item, area) -- formate la ligne concernant la rue et le numéro de rue
	local streets -- châine contenant le ou les rues et numéros d'immeuble
	
	if not area then
		local country = getCountry(item)
		if country and formats[country] then
			area = formats[country]
		else
			area = formats.default
		end
	end
	
	-- essaye de remplir street, en priorité avec P669, type : élément
	local streetclaims = wikidata.getClaims{entity = item, property = 'P669'}
	if streetclaims then
		for i, j in pairs(streetclaims) do
			streetclaims[i] = wikidatastreet(j, area)
		end
		streets = mw.text.listToText(streetclaims)
		streets = wikidata.formatAndCat{value = streets, entity = item, property = 'P669'}
	end
	
	-- sinon : P6375, type : string -- remplace P969
	if not streets then
		streets = wikidata.formatAndCat{linkback = true, property = 'P6375', entity = item, isinlang = 'fr'}
	end
	
	-- sinon : P969, type : string -- propriété obsolète
	if not streets then 
		streets =  wikidata.formatAndCat{linkback = true, property = 'P969', entity = item}
	end
	
	return streets
end

function p.adminDivList(item, country) -- returns a list of admin divisions matching the criteria defined in Module:Adresse/Formats
	country = country or getCountry(item)
	local query = {property = 'P131'}
	local divs = wikidata.transitiveVals(item, query, 0, 10, country)
	local validDivs = {}	
	
	-- solution 1: looks for divs of a certain type
	local function setValue(targetclasses, depth)
		local test = {}
		for _, d in pairs(divs) do
			for j, divtype in pairs(targetclasses) do
				if (divtype == '-') then
					if #validDivs > 0 then
						divs = wikidata.addVals(divs, query, 0, 1, country)
					end
					if divs[#divs] == country then
						return nil
					end
					return divs[#divs]
				end
				if wikidata.isInstance(divtype, d, 3) then
					 -- restrain list to new value, will be expanded only if needed
					divs = {d}
					return d
				end
			end
		end
		if depth >= 0 then
			local num = #divs
			divs = wikidata.addVals(divs, query, 0, 10, country)
			if #divs > num then return setValue(targetclasses, depth) end
		end
	end

	-- solution2: looks for divs that are part of a closed list (way more efficient for big items)
	local function findInList(list, depth) 
		for i, j in pairs(divs) do
			for k, l in pairs(list) do
				if j == l then
					divs = {l}
					return l
				end
			end
		end
		if depth >= 0 then
			local num = #divs
			divs = wikidata.addVals(divs, query, 0, 10, country)
			if #divs > num then return findInList(list, depth) end
		end
	end
					
	local displayformat = formats[country] or formats.default
	local maxdepth = 3
	if not divs then
		return nil
	end

	if displayformat.div1 then
		local val = setValue(displayformat.div1, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end

	if displayformat.div2 then
		local val = setValue(displayformat.div2, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	elseif displayformat.div2vals then
		local val =  findInList(displayformat.div2vals, 1)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end
	
	if displayformat.div3 then
		local val = setValue(displayformat.div3, maxdepth)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	elseif displayformat.div3vals then
		local val =  findInList(displayformat.div3vals, 0)
		if val and val ~= validDivs[#validDivs] then
			table.insert(validDivs, val)
		end
	end
	
	return validDivs
end

function p.cityLine(item, country, divlist, postcode) -- line with list of admin divisions + optional postcode
	country = country or getCountry(item)
	
	local postcode = postcode or wikidata.formatStatements{entity = item, property = 'P281'} or ''
	if postcode == '-' then -- can be disabled when it is not useful
		postcode = ''
	end
	local divstr = ''
	
	if (not divlist) or (#divlist == 0) then
		divlist = p.adminDivList(item, country)
	end
	if (not divlist) or (#divlist == 0) then
		return -- add a maintenance category ?
	end
	for i, j in pairs(divlist) do
		if string.find(j, '^Q[0-9]+$') then
			divlist[i] = wikidata.formatEntity(j)
		end
	end
	local divstr = linguistic.conj(divlist, 'comma')

	local formatting = formats[country] or formats.default
	local str = formatting.cityline or formats.default.cityline
	str = str:gsub("$postcode", postcode or '')
	str = str:gsub("$admindivs", divstr or '')
	return str
end

function p.fullAddress(item, country, divs, streetstr, divstr, showcountry, postcode)
	 -- country id used for formatting
	country = country or getCountry(item)
	local displayformat = formats[country] or formats.default

	-- line 1 street
	local streetline = streetstr or p.streetAddress(item, country)
	
	-- line 2: administrative divisions, postcodes
	local cityline = divstr
	if not cityline then cityline = p.cityLine(item, country, divs, postcode) end
	if (not cityline) or mw.text.trim(cityline) == '' then
		cityline = nil
	end

	-- line 3: country
	local countryline, success
	if (showcountry ~= '-') then
		countryline, success = countrymodule.standarddisplay(country)
		if not success then
			if (type(country) == 'string') and string.find(country, "^Q[0-9]+$") then
				countryline = wikidata.formatEntity(country)
			else
				countryline = country or wikidata.formatStatements{entity = item, property = 'P17'}
			end
		end
	end
	local str = linguistic.conj({streetline, cityline, countryline}, '<br />')
	if str and (not streetstr) and (not divstr) then -- à peu près
		str = str .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
	end
	
	local hasstreetline
	if streetline then hasstreetline = true else hasstreetline = false end

	return str, hasstreetline
end

function p.wikidataAddress(item, country) -- fonction de transition
	local area = formats[country] or formats.default
	local val = p.streetAddress(item, area)
	if val then
		return val .. '[[Category:Page utilisant une adresse fournie par Wikidata]]'
	end
end
return p