Module:Wikidata

De Baripedia

Erreur Lua : impossible de créer le processus : proc_open n’est pas disponible. Vérifiez la directive de configuration PHP « disable_functions ». This module is a modification of the original at Module:Sandbox/Tom Morris which was created 19 May 2013.

The module "Wikidata" contains:

  • a call (getValue) that allows the calling script to retrieve the wiki-linked value(s) for any property from Wikidata by supplying the property ID as the first parameter.
  • a call (getRawValue) that allows the calling script to retrieve the non-linked value(s) for any property from Wikidata by supplying the property ID as the first parameter.
  • a call (getDateValue) that allows the calling script to retrieve the date value(s) for any property from Wikidata by supplying the property ID as the first parameter. It allows specifying that the date be returned in dmy or mdy format by supplying "dmy" or "mdy" as an optional third parameter.

If the property is not defined in Wikidata for the article that invokes this code, then an empty string ("") is returned.

Parameters[modifier le wikicode]

  • For the generalised linked case (getValue), two unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. p19 for birthplace or p26 for spouse). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value.
  • For the generalised unlinked case (getRawValue), two unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. p21 for gender). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value.
  • For the generalised date case (getDateValue), three unnamed parameters are supplied. The first is the ID of the property that is to be retrieved (e.g. p569 for date of birth). The second may be null, "FETCH_WIKIDATA", or any other string, which becomes the returned value. The third is the format that the date should be returned in, either dmy or mdy.

Usage[modifier le wikicode]

Example:spouse[modifier le wikicode]

  • {{#invoke:Wikidata|getValue|p26|}} = returns nothing, so suppresses the display of spouse in an infobox
  • {{#invoke:Wikidata|getValue|p26|FETCH_WIKIDATA}} = returns the linked value(s) of property p26 (spouse) stored in wikidata for the corresponding article (e.g. for article Bill Clinton, it returns Hillary Rodham Clinton)
  • {{#invoke:Wikidata|getValue|p26|[[Hillary Clinton]]}} = returns Hillary Clinton, allowing an infobox to use a local value rather than the value stored in Wikidata.

Example in Infobox template[modifier le wikicode]

Inside an infobox definition, it may be called like this:

  • | data55 = {{#invoke:Wikidata|getValue|p26|{{{spouse|FETCH_WIKIDATA}}} }}

which causes the infobox to:

  1. not display spouse if the infobox parameter |spouse is set to be blank (as "| spouse ="}
  2. display the linked value(s) from Wikidata if the infobox parameter |spouse is not supplied
  3. display the local infobox parameter |spouse if it is supplied (e.g. "|spouse = Hillary Clinton")

Optionally, it could be called as:

  • | data55 = {{#invoke:Wikidata|getValue|p26|{{{spouse|}}} }}

which should behave as the parameter does now, unless the parameter is set to FETCH_WIKIDATA when it displays the linked value(s) fetched from Wikidata.

Example:birth place[modifier le wikicode]

This works in just the same way as the calls above:

  • {{#invoke:Wikidata|getValue|p19|}} = returns nothing, so suppresses the display of birth place in an infobox
  • {{#invoke:Wikidata|getValue|p19|FETCH_WIKIDATA}} = returns the linked value(s) of property p19 (place of birth) stored in wikidata for the corresponding article (e.g. for article Bill Clinton, it returns Hope, Arkansas)
  • {{#invoke:Wikidata|getValue|p19|[[Hope, Arkansas|Hope]]}} = returns Hope, allowing an infobox to use a local value rather than the value stored in Wikidata.

Example:gender[modifier le wikicode]

We don't want the returned value linked, so use:

  • - {{#invoke:Wikidata|getRawValue|p21|FETCH_WIKIDATA}}

Example:date of birth[modifier le wikicode]

If we want the date of birth in dmy format, we use:

  • - {{#invoke:Wikidata|getDateValue|p569|FETCH_WIKIDATA|dmy}}

If we want the date of birth in mdy format, we use:

  • - {{#invoke:Wikidata|getDateValue|p569|FETCH_WIKIDATA|mdy}}

Testing[modifier le wikicode]

Testing spouse[modifier le wikicode]

Copy and paste the following into any article and preview it (please don't save!):

* - {{#invoke:Wikidata|getValue|p26|}}
* - {{#invoke:Wikidata|getValue|p26|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getValue|p26|[[Hillary Clinton]]}}

In Bill Clinton you should get:


In Barack Obama you should get:


In Richard Burton you should get:


In Franz Kafka you should get:

Testing birthplace[modifier le wikicode]

Copy and paste the following into any article and preview it (please don't save!):

* - {{#invoke:Wikidata|getValue|p19|}}
* - {{#invoke:Wikidata|getValue|p19|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getValue|p19|[[Newport]]}}

Try William Ellery and check that the Wikidata call correctly disambiguates.

Testing getValue, getRawValue and getDateValue[modifier le wikicode]

Copy and paste the following into any article and preview it (please don't save!):

* - {{#invoke:Wikidata|getValue|p19|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getValue|p26|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getValue|p27|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getValue|p140|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getRawValue|p21|FETCH_WIKIDATA}}
* - {{#invoke:Wikidata|getDateValue|p569|FETCH_WIKIDATA|dmy}}
* - {{#invoke:Wikidata|getDateValue|p569|FETCH_WIKIDATA|mdy}}

This should return the Wikidata values for birthplace, spouse, citizenship, religion, gender and date of birth (twice) if they exist. The dob is first in dmy format and then in mdy.


Erreur de script : Erreur Lua : impossible de créer le processus : proc_open n’est pas disponible. Vérifiez la directive de configuration PHP « disable_functions ».

--script that retrieves basic data stored in Wikidata, for the datamodel, see https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua

wd = wd or {}
reference = reference or require "Module:Wikidata/Références"

local linguistic = require "Module:Linguistique"
local formatDate = require "Module:Date complexe"
local formatNum = require 'Module:Conversion'
local units = require 'Module:Dictionnaire Wikidata/Unités'
local langmodule = require'Module:Langue'
local cite = require "Module:Biblio"
local langcodes = mw.loadData "Module:Dictionnaire Wikidata/Codes langue"
local getData = require 'Module:Wikidata/Récup'
local entities = require 'Module:Wikidata/Formatage entité'
local tools = require 'Module:Wikidata/Outils'
local defaultlang = mw.getContentLanguage():getCode()

local translate = tools.translate

function wd.addtrackingcat(prop, cat) -- doit parfois être appelé par d'autres modules
	if not prop and not cat then
		return error("no property provided")
	end
	if not cat then
		cat = translate('trackingcat', prop or 'P??')
	end
	return tools.addcat(cat )
end

local function removeblanks(args)
	for i, j in pairs(args) do
		if j == '' then args[i] = nil end
	end
	return args
end

local function unknownvalue(displayformat) -- à améliorer
	if not displayformat then
		return translate('somevalue')
	end
	if type(displayformat) == 'string' then
		return displayformat
	end
	return tools.formatError()
end

local function novalue(displayformat)
	if not displayformat then
		return translate('novalue')
	end
	if type(displayformat) == 'string' then
		return displayformat
	end
	return tools.formatError()
end

local function getlangcode(entityid)
	return langcodes[tonumber(entityid:sub(2))]
end

local  function showlang(statement) -- retourne le code langue entre paranthèse avant la valeur (par exemple pour les biblios et liens externes)
	local mainsnak = statement.mainsnak
	if mainsnak.snaktype ~= 'value' then
		return nil
	end
	local langlist = {}
	if mainsnak.datavalue.type == 'monolingualtext' then
		langlist = {mainsnak.datavalue.value.language}
	elseif (not statement.qualifiers) or (not statement.qualifiers.P407) then
		return
	else
		for i, j in pairs( statement.qualifiers.P407 ) do
			if  j.snaktype == 'value' then
				local langentity = tools.getId(j)
				local langcode =  getlangcode(langentity)
				table.insert(langlist, langcode)
			end
		end
	end
	if (#langlist > 1) or (#langlist == 1 and langlist[1] ~= defaultlang) then -- si c'est en français, pas besoin de le dire
		return langmodule.indicationMultilingue(langlist)
	end
end

local function formattable(statements, params) -- transform a table of claims into a table of formatted values
    for i, j in pairs(statements) do
        j = wd.formatStatement(j, params)
    end
    return statements
end

local function tableToText(values, params) -- takes a list of already formatted values and make them a text
    if not values then
        return nil
    end
    return linguistic.quickconj( values, params.conjtype)--linguistic.conj( values, params.lang, params.conjtype )
end


function wd.rangeobject(begin, ending, params)
	--[[
		objet comportant un timestamp pour le classement chronologique et deux dateobject (begin et ending)
	]]-- 
	local timestamp
	if begin then
		timestamp = begin.timestamp
	else
		timestamp = ending.timestamp
	end
	return {begin = begin, ending = ending, timestamp = timestamp, type = 'rangeobject'}
end

function wd.dateobject(orig, params)
	--[[ 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}
	]]-- 
	if not params then
		params = {}
	end
	
	local newobj = formatDate.splitDate(orig.time, orig.calendar)
	
	newobj.precision = params.precision or orig.precision
	newobj.type = 'dateobject'
	return newobj
end

function wd.objecttotext(obj, params)
	if obj.type == 'dateobject' then
		return formatDate.simplestring(obj, params)
	elseif obj.type == 'rangeobject' then
		return formatDate.daterange(obj.begin, obj.ending, params)
	end
end


function wd.getDate(statement)
--[[
returns an object containing a timestamp for easy sorting, and other data
	2 types of object
		dateobject
			{timestamp = string, year = number, month = number, day = number, calendar = string}
		rangeobject
			{timestamp = string, begin = dateobject, ending = dateobject}
]]--
	local q = statement.qualifiers
	if not q or not (q.P585 or q.P580 or q.P582) then
		return nil
	end
	local begin, ending
	-- si p585 : dateobject
	if q.P585 and q.P585[1].snaktype == 'value' then -- P585: punctual date
		return wd.dateobject(q.P585[1].datavalue.value)
	end

	-- si p580 ou P582 : rangeobject avec une date de début et/ou une date de fin
	if q.P582 and q.P582[1].snaktype == 'value' then
		ending = wd.dateobject(q.P582[1].datavalue.value)
	end
	if (q.P580 and q.P580[1].snaktype == 'value') then
		begin = wd.dateobject(q.P580[1].datavalue.value)
	end
	if begin or ending then -- sinon ce sont des 'specialvalues', il faudrait aussi les prendre en charge
		return wd.rangeobject(begin, ending)
	end
end

function wd.getFormattedDate(statement, params)
	local datetable = wd.getDate(statement)
	if not datetable then
		return nil
	end
	return wd.objecttotext(datetable, params)
end


function wd.getDatavalue(snak, params)
	if not params then
		params = {}
	end
	local speciallabels = params.speciallabels -- parfois on a besoin de faire une liste d'éléments pour lequel le libellé doit être changé, pas très pratique d'utiliser une fonction pour ça

	if snak.snaktype ~= 'value' then
		return nil
	end

	local datatype = snak.datavalue.type
	local value = snak.datavalue.value
	
	local displayformat = params.displayformat
	if type(displayformat) == 'function' then
        return displayformat(snak, params)
 	end

	if (datatype == 'wikibase-entityid') then
		return entities.formatEntity(tools.getId(snak), params)
	end

	if datatype == ('string') then
		if params.displayformat == 'weblink' then
			return require('Module:Weblink').makelink(value, params.text)
		end
		if type(params.displayformat) == 'function' then
			value = params.displayformat(value)
		end
		if params.urlpattern then
			local urlpattern = params.urlpattern
			if type(urlpattern) == 'function' then
				urlpattern = urlpattern(value)
			end
			value = '[' .. mw.ustring.gsub(urlpattern, '$1', value) .. ' ' .. (params.text or value) .. ']'
		end
		return value
	end
	
	if datatype == 'time' then -- format example: +00000001809-02-12T00:00:00Z
		local precision = params.precision -- degré de précision à afficher ('day', 'month', 'year'), inférieur ou égal à value.precision
		if displayformat == 'raw' then
			return value.time
		else
			return wd.objecttotext(wd.dateobject(value, {precision = precision}), {linktopic = params.linktopic})
		end
	end

	if datatype == 'globecoordinate' then
		-- retourne une table avec clés latitude, longitude, précision et globe à formater par un autre module (à changer ?)
		value.globe = require('Module:Wikidata/Globes')[value.globe] -- transforme l'ID du globe en nom anglais utilisable par geohack
		if formatting == 'latitude' then
			return value.latitude
		elseif formatting == 'longitude' then
			return value.longitude
		else
			return value -- note : les coordonnées Wikidata peuvent être utilisée depuis Module:Coordinates. Faut-il aussi autoriser à appeler Module:Coordiantes ici ?
		end
	end

	if datatype == 'quantity' then -- todo : gérer les paramètre précision
		local amount, unit = value.amount, value.unit
 		if displayformat == 'raw' then
			return amount
		end
		local showunit = params.showunit or true		
		if showunit == '-' then
			showunit = false
		end
		local targetunit = params.targetunit
		if unit and showunit then --récupération des données sur l'unité
			local unititem = unit:match('Q%d+')
			unit = units[unititem]
			if (not unit) then -- si pas de données sur l'unité, on essaye dans l'élément
				unit = {
					[3] = wd.formatStatements{entity = unititem, property = 'P558'}, -- symbole de l'unité
					[6] = wd.getLabel(unititem),
				}
			end
		end
		
		return formatNum.displayvalue(amount, unit,
			{targetunit = params.targetunit, displayformat = params.displayformat, rounding = params.rounding, showunit = showunit}
			)
	end
	if datatype == 'monolingualtext' then
		return langmodule.langue({value.language, value.text})
	end
	
	return tools.formatError('unknown-datavalue-type' )
    
end

function wd.getClaims( args ) -- returns a table of the claims matching some conditions given in args
	return getData.getClaims(args)
end

function wd.formatClaimList(claims, args)
    if not claims then
        return nil
    end
	for i, j in pairs(claims) do
        claims[i] = wd.formatStatement(j, args)
    end
    if args.removedupes and (args.removedupes ~= '-') then
		claims = tools.addnewvalues({}, claims)
	end
    return claims
end

function wd.stringTable(args) -- like getClaims, but get a list of string rather than a list of snaks, for easier manipulation
	local claims = wd.getClaims(args)
	return wd.formatClaimList(claims, args)
end


local function getQualifiers(statement, qualifs, params)
	if not statement.qualifiers then
		return nil
	end
	local vals = {}
	for i, j in pairs(qualifs) do
		if statement.qualifiers[j] then
			for k, l in pairs(statement.qualifiers[j]) do
				table.insert(vals, l)
			end
		end
	end
	if #vals == 0 then
		return nil
	end
	return vals
end

function wd.getFormattedQualifiers(statement, qualifs, params)
	if not params then params = {} end
	local qualiftable = getQualifiers(statement, qualifs)
	if not qualiftable then
		return nil
	end
	for i, j in pairs(qualiftable) do
		qualiftable[i] = wd.formatSnak(j, params)
	end
	return linguistic.conj(qualiftable)
end

function wd.formatStatement( statement, args )
	if not args then
		args = {}
	end
    if not statement.type or statement.type ~= 'statement' then
        return tools.formatError( 'unknown-claim-type' )
    end
    local str = wd.formatSnak( statement.mainsnak, args )
    if args.showlang == true then
    	str = (showlang(statement) or '') .. ' ' .. str
    end
    if args.showqualifiers then
    	local qualifs =  args.showqualifiers
    	if type(qualifs) == 'string' then
    		qualifs = mw.text.split(qualifs, ',')
    	end
    	local qualifargs = {}
 		-- formatage des qualificateur = args commençant par "qualif", ou à défaut, les mêmes que pour la valeur principale
    	qualifargs.displayformat = args.qualifdisplayformat or args.displayformat
    	qualifargs.labelformat = args.qualiflabelformat or args.labelformat
    	qualifargs.link = args.qualiflink or args.link
    	
    	local formattedqualifs = wd.getFormattedQualifiers(statement, qualifs, qualifargs)
    	if formattedqualifs then
    		str = str .. linguistic.inparentheses(formattedqualifs, lang)
		end
	end

    if args.showdate then -- when "showdate and chronosort are both set, date retrieval is performed twice
    	local timedata = wd.getDate(statement)
    	if timedata then
    		local formatteddate = wd.objecttotext(timedata, args)
    		formatteddate = linguistic.inparentheses(formatteddate, lang)
    		str = str .. '<small>' .. formatteddate ..'</small>'
    	end
    end

	if args.showsource and statement.references then
		local sourcestring = ''
		for i, ref in pairs(statement.references) do
			local s = ''
			
			local function hasValue(prop) -- checks that the prop is here with valid value
				if ref.snaks[prop] and ref.snaks[prop][1].snaktype == 'value' then
					return true
				end
				return false
			end
			local function firstsnak(prop)
				return wd.formatSnak(prop[1])
			end
			if ref.snaks.P248 then
				for j, source in pairs(ref.snaks.P248) do
					if source.snaktype == 'value' then
						local page, accessdate
						if hasValue('P304') then
							page = wd.formatSnak(ref.snaks.P304[1])
						end
						if hasValue('P813') then
							accessdate = wd.formatSnak(ref.snaks.P813[1])
						end
						s = reference.citeitem(tools.getId(source), {['page'] = page, ['accessdate'] = accessdate})
						s = mw.getCurrentFrame():extensionTag( 'ref', s )
						sourcestring = sourcestring .. s
					end
				end
			elseif hasValue('P854') and hasValue('P1476') then
				local url, title, accessdate, publishdate, publishlang
				url, title = wd.formatSnak(ref.snaks.P854[1]), wd.formatSnak(ref.snaks.P1476[1])
				if hasValue('P813') then
					accessdate = wd.formatSnak(ref.snaks.P813[1])
				end
				-- publishdate avec P577 ? (ne semble pas vraiment correspondre) 
				if hasValue('P407') then
					local id = tools.getId(ref.snaks.P407[1])
					publishlang = getlangcode(id)
				end
				s = cite.lienWeb{titre = title, url = url, langue = publishlang, ['en ligne le'] = publishdate, ['consulté le'] = accessdate}
				s = mw.getCurrentFrame():extensionTag( 'ref', s)
				sourcestring = sourcestring .. s
			elseif ref.snaks.P854 and ref.snaks.P854[1].snaktype == 'value' then
				s = mw.getCurrentFrame():extensionTag( 'ref', wd.formatSnak(ref.snaks.P854[1]))
				sourcestring = sourcestring .. s
			end
			end
			str = str .. sourcestring
		end
		return str
end

function wd.formatSnak( snak, params )
    if not params then params = {} end -- pour faciliter l'appel depuis d'autres modules
    if snak.snaktype == 'somevalue' then
        return unknownvalue(params.unknownlabel)
    elseif snak.snaktype == 'novalue' then
        return novalue(params.novaluelabel)
    elseif snak.snaktype == 'value' then
        return wd.getDatavalue( snak, params)
    else
        return tools.formatError( 'unknown-snak-type' )
    end
end

function wd.getDescription(entity, lang)
	lang = lang or defaultlang

	local description
	if lang == defaultlang then
		return  mw.wikibase.descriptionl(qid)
	end
    if not entity.descriptions then
    	return translate('no description')
    end
    local descriptions = entity.descriptions
    if not descriptions then
    	return nil
    end
    if descriptions[lang] then
    	return descriptions[delang].value
    end
    return entity.id
end

function wd.addLinkback(str, id, property)
	if not id then
		id = tools.getEntity()
	end
	if type(id) == 'table' then
		id = id.id
	end
	
	local class = ''
	if property then
		class = 'wd_' .. string.lower(property)
	end
	local title = translate('see-wikidata-value')
	local icon = '[%s [[File:Blue pencil.svg|%s|10px|baseline|link=]] ]'
	local url = mw.uri.fullUrl('d:' .. id, 'uselang=fr')
	url.fragment = property
	url = tostring(url)
	local v = mw.html.create('span')
		:addClass(class)
		:wikitext(str)
		:tag('span')
			:addClass('noprint plainlinks wikidata-linkback')
			:css('padding-left', '.5em')
			:wikitext(icon:format(url, title))
		:allDone()
	return tostring(v)
end

function wd.addRefAnchor(str, id)
--[[
    Insère une ancre pour une référence générée à partir d'un élément Wikidata.
    L'id Wikidata sert d'identifiant à l'ancre, à utiliser dans les modèles type "harvsp"
--]]
    return tostring(mw.html.create('span'):attr('id', id)
    	                                  :attr('class', "ouvrage")
    	                                  :wikitext(str)
    	            )
end

function wd.formatStatements( args )--Format statement and concat them cleanly
	if args.value == '-' then
		return nil
	end
	--If a value is already set, use it
	if args.value and args.value ~= '' then
		return args.value
	end
	args.entity = tools.getEntity(args.entity)
	local valuetable = wd.stringTable(args)
	
	local str = tableToText(valuetable, args)
	
	if not str then
		return nil
	end
	if args.addcat and (args.addcat ~= '-') then
		str = str .. wd.addtrackingcat(args.property)
	end
	if args.linkback and (args.linkback ~= '-') then
		str = wd.addLinkback(str, args.entity, args.property)
	end
	return str
end

function wd.showQualifier( args )
	local qualifs = args.qualifiers or args.qualifier
	if type(qualifs) == 'string' then
		qualifs = mw.text.split(qualifs, ',')
	end
	if not qualifs then
		return tools.formatError( 'property-param-not-provided' )
	end
	local claims = wd.getClaims(args)
	if not claims then
		return nil
	end
	local str = ''
	for i, j in pairs(claims) do
		local new = wd.getFormattedQualifiers(j, qualifs, args) or ''
		str = str .. new
	end
	return str
end

function wd.formatAndCat(args)
	if not args then
		return nil
	end
	args.linkback = true
	args.addcat = true
	if args.value then -- do not ignore linkback and addcat, as formatStatements do
		local val = args.value .. wd.addtrackingcat(args.property)
		val = wd.addLinkback(val, args.entity, args.property)
		return val
	end
	return wd.formatStatements( args )
end

function wd.getTheDate(args)
	local claims = wd.getClaims(args)
	if not claims then
		return nil
	end
	local formattedvalues = {}
	for i, j in pairs(claims) do
		table.insert(formattedvalues, wd.getFormattedDate(j))
	end
	local val = linguistic.conj(formattedvalues)
	if not val then
		return nil
	end
	if args.addcat == true then
		val = val .. wd.addtrackingcat(args.property)
	end
	val = wd.addLinkback(val, args.entity, args.property)
	return val
end


-- Complex functions using several items
local function getids(query)
	query.excludespecial = true
	query.displayformat = 'raw'
	return wd.stringTable(query)
end


function wd.Dump(entity)
	entity = tools.getEntity(entity)
	if not entity then
		return tools.formatError("entity-param-not-provided")
	end
	return "<pre>"..mw.dumpObject(entity).."</pre>"
end

wd.getid = tools.getId
wd.getmainid = tools.getMainId

-- fonctions obsolètes
function wd.getLabel(entity, args)
	entities.getLabel(entity)
end

function wd.formatEntity(entity, args)
	return entities.formatEntity(entity, args)
end

function wd._getLabel(entity, args)
	return wd.getLabel(entity, args)
end

function wd._formatAndCat(args)
	return wd.formatAndCat(args)
end
function wd._formatStatements(args)
	return wd.formatStatements(args)
end
return wd