Module:Wikidata
<templatestyles src="Module:Message box/ombox.css"></templatestyles>
| This module is rated as alpha. It is ready for third party input, and may be used on a few pages to see if problems arise, but should be watched. Suggestions for new features or changes in their input and output mechanisms are welcome. |
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:
- not display spouse if the infobox parameter
|spouseis set to be blank (as"| spouse ="} - display the linked value(s) from Wikidata if the infobox parameter
|spouseis not supplied - display the local infobox parameter
|spouseif 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:
- -
- -
- - Hillary Clinton
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.
--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