Module:InfoboxWB
From Bahaipedia
This is a helper module for retrieving data from bahaidata.org. It is intended to be referenced by a template which is used on a page that is already connected to a wikibase item. It does not support retrieving specific items or their properties from bahaidata since this module is specific to infoboxes used on pages which should always have a corresponding connected bahaidata page.
Functions[edit]
- getImage
- getImageCaption
- getBirthName
- getBirthDate
- getBirthPlace
- getBirthCountry
- getDeclarationDate
- getDeathDate
- getDeathPlace
- getDeathCountry
- getDeceasedAge (The age of the individual at the time of their death)
- getSisterProjects
Parameters[edit]
- lang, used to specify a language you want retrieved and displayed if other then English. If the requested language value doesn't exist then the English language value is displayed.
- format, used to modify the display format for dates, options are mdy (default) and dmy
Examples[edit]
Basic[edit]
- {{#invoke:InfoboxWB|getDeathPlace}}
- {{#invoke:InfoboxWB|getImageCaption}}
- {{#invoke:InfoboxWB|getDeathDate}}
Lang parameter[edit]
- {{#invoke:InfoboxWB|getImageCaption|lang=es}}
Format parameter[edit]
- {{#invoke:InfoboxWB|getDeathDate|format=dmy}}
To do[edit]
The adaptation so far is intended for use with Template:Infobox Person but more infoboxes can be supported by adding more functions. Need to identify other data which is suitable, what functions are needed and add/test/integrate them back into the respective templates.
-- Module:InfoboxWB
local p = {}
local mw = require('mw')
-- Helper function to determine if a page is connected to bahaidata
function p.isEntityConnected()
local entity = mw.wikibase.getEntity()
return entity ~= nil
end
-- Helper function to fetch property value from entity
local function fetchPropertyValue(entity, propertyId)
if not entity or not propertyId then
return nil
end
local property = entity:getBestStatements(propertyId)[1]
if property and property.mainsnak and property.mainsnak.datavalue then
return property.mainsnak.datavalue.value.id or property.mainsnak.datavalue.value
end
return nil
end
-- Helper function to fetch sitelink from entity
--local function fetchSiteLinkValue(entity, site)
-- if not entity or not site then
-- return nil
-- end
-- local siteLink = entity:getSiteLink(site)[1]
-- if siteLink and siteLink.mainsnak and siteLink.mainsnak.datavalue then
-- -- Assuming the property value is a simple string or a numeric ID
-- return siteLink.mainsnak.datavalue.value.id or siteLink.mainsnak.datavalue.value
-- end
-- return nil
--end
-- Function to get the label of an item in a specified language
local function getItemLabel(itemId, lang)
if not itemId then
return nil
end
local item = mw.wikibase.getEntity(itemId)
if item then
local label = item:getLabel(lang) -- Attempt to get the label in the specified language
if label then
return label
else
return item:getLabel('en') -- Fallback to English label if specified language label is not available
end
end
return nil
end
-- Function to fetch monolingual text properties with a fallback to English
function p.getMonolingualText(entity, propertyId, lang)
local statements = entity:getBestStatements(propertyId)
local fallbackText = nil -- Variable to store the English text
for _, statement in ipairs(statements) do
if statement.mainsnak and statement.mainsnak.datavalue then
local textData = statement.mainsnak.datavalue.value
if textData and textData.text then
if textData.language == lang then
return textData.text -- Return the text for the specified language
elseif textData.language == 'en' then
fallbackText = textData.text -- Store the English text as a fallback
end
end
end
end
return fallbackText -- Return the English text if no text in the specified language is found
end
-- Function to fetch monolingual qualifiers of a property with a fallback to English
function p.getMonolingualTextFromQualifier(qualifiers, propertyId, lang)
local fallbackText = nil -- Variable to store the English text
if qualifiers and qualifiers[propertyId] then
for _, qualifier in ipairs(qualifiers[propertyId]) do
if qualifier.datavalue then
local textData = qualifier.datavalue.value
if textData and textData.text then
if textData.language == lang then
return textData.text -- Return the text for the specified language
elseif textData.language == 'en' then
fallbackText = textData.text -- Store the English text as a fallback
end
end
end
end
end
return fallbackText -- Return the English text if no text in the specified language is found
end
-- Function to format dates
local function formatDate(timeValue, format)
if not timeValue or type(timeValue) ~= 'table' or not timeValue.time then
return nil
end
-- Extracting the time string from the timeValue table
local timeString = timeValue.time
if not timeString then
return nil
end
-- The time string might start with a '+' sign, which needs to be removed for formatting
timeString = timeString:gsub("^%+", "")
-- Formatting the date
if format == 'dmy' then
return mw.language.getContentLanguage():formatDate('j F Y', timeString)
else -- default to 'mdy'
return mw.language.getContentLanguage():formatDate('F j, Y', timeString)
end
end
function p.getImage(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then
return nil -- No entity ID, return nil
end
local entity = mw.wikibase.getEntity(entityId)
if not entity then
return nil -- No entity data, return nil
end
local imageProperty = entity:getBestStatements('P35')[1]
if imageProperty and imageProperty.mainsnak and imageProperty.mainsnak.datavalue then
local image = imageProperty.mainsnak.datavalue.value
if image then
return image -- Return the image filename
end
end
return nil -- No image found, return nil
end
function p.getImageCaption(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then
return nil -- No entity ID, return nil
end
local entity = mw.wikibase.getEntity(entityId)
if not entity then
return nil -- No entity data, return nil
end
local statements = entity:getBestStatements('P35')
if #statements == 0 then
return nil -- No image property, return nil
end
local imageProperty = statements[1]
local lang = frame.args.lang or 'en'
return p.getMonolingualTextFromQualifier(imageProperty.qualifiers, 'P40', lang)
end
function p.getBirthName(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local lang = frame.args.lang or 'en'
return p.getMonolingualText(entity, 'P41', lang)
end
function p.getBirthDate(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local birthDate = fetchPropertyValue(entity, 'P16')
-- Check if birthDate contains only a year (e.g., '+1960-00-00T00:00:00Z')
if birthDate and type(birthDate) == 'table' and birthDate.time and string.match(birthDate.time, "^%+%d%d%d%d%-00%-00") then
return string.sub(birthDate.time, 2, 5)
end
return birthDate and formatDate(birthDate, frame.args.format)
end
function p.getDeclarationDate(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local declarationDate = fetchPropertyValue(entity, 'P45')
-- Check if declarationDate contains only a year (e.g., '+1960-00-00T00:00:00Z')
if declarationDate and type(declarationDate) == 'table' and declarationDate.time and string.match(declarationDate.time, "^%+%d%d%d%d%-00%-00") then
return string.sub(declarationDate.time, 2, 5)
end
return declarationDate and formatDate(declarationDate, frame.args.format)
end
function p.getBirthPlace(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local birthPlaceId = fetchPropertyValue(entity, 'P19')
local lang = frame.args.lang or 'en'
return getItemLabel(birthPlaceId, lang)
end
function p.getBirthCountry(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local birthPlaceId = fetchPropertyValue(entity, 'P19')
if not birthPlaceId then return nil end
local birthPlaceEntity = mw.wikibase.getEntity(birthPlaceId)
local countryId = fetchPropertyValue(birthPlaceEntity, 'P37')
local lang = frame.args.lang or 'en'
return getItemLabel(countryId, lang)
end
function p.getPositionsWithDates(frame)
local entity = mw.wikibase.getEntity()
local statements = entity:getBestStatements('P55') -- Position held
if not statements or #statements == 0 then
return ""
end
local lang = frame.args.lang or 'en'
local positionData = {}
-- Define a mapping for institution prefixes to their full names and link text
local institutionMapping = {
["NSA"] = {link = "National Spiritual Assembly", text = "NSA member"},
["Universal House of Justice"] = {link = "Universal House of Justice", text = "UHJ member"},
["International Teaching Centre"] = {link = "International Teaching Centre", text = "ITC member"},
["LSA"] = {link = "Local Spiritual Assembly", text = "LSA member"},
["Auxiliary Board for"] = {link = "Auxiliary Board", text = "ABM"},
["Continental Board of Counsellors for"] = {link = "Continental Boards of Counsellors", text = "Counsellor"},
["International Bahá’í Council"] = {link = "International Bahá'í Council", text = "IBC member"},
["Custodian"] = {link = "Custodian", text = "Custodian"}
}
for _, statement in ipairs(statements) do
local mainsnak = statement.mainsnak
if mainsnak and mainsnak.datavalue then
local positionId = mainsnak.datavalue.value.id
local label = getItemLabel(positionId, lang) or positionId
-- Determine institution and display name
local prefix, displayName
local institution
if label:match("^(NSA):(.+)$") or label:match("^(LSA):(.+)$") then
-- Extract the prefix and location for NSA and LSA
prefix, displayName = label:match("^(%a+):(.+)$")
institution = institutionMapping[prefix]
elseif label:find("^Auxiliary Board for") or label:find("^Continental Board of Counsellors for") then
-- Extract the region for Auxiliary Board and Continental Board
local pattern = "^(Auxiliary Board for) (.+)$"
if label:find("^Continental Board of Counsellors for") then
pattern = "^(Continental Board of Counsellors for) (.+)$"
end
prefix, displayName = label:match(pattern)
institution = institutionMapping[prefix]
else
-- Handle full names directly for other specific institutions
displayName = label
institution = institutionMapping[label]
end
-- Get qualifiers
local qualifiers = statement.qualifiers or {}
local startTime = qualifiers['P56'] and qualifiers['P56'][1] and qualifiers['P56'][1].datavalue and qualifiers['P56'][1].datavalue.value.time
local endTime = qualifiers['P57'] and qualifiers['P57'][1] and qualifiers['P57'][1].datavalue and qualifiers['P57'][1].datavalue.value.time
local startYear = startTime and mw.ustring.match(startTime, "%d%d%d%d")
local endYear = endTime and mw.ustring.match(endTime, "%d%d%d%d")
table.insert(positionData, {
label = label,
displayName = displayName,
institution = institution,
startYear = startYear,
endYear = endYear,
sortKey = startTime or "9999" -- Put undated entries at the end
})
end
end
-- Sort by sortKey (chronological order)
table.sort(positionData, function(a, b)
return a.sortKey < b.sortKey
end)
-- Format results
local results = {}
for _, entry in ipairs(positionData) do
if entry.institution then
local dateStr = ""
if entry.startYear and entry.endYear then
dateStr = entry.startYear .. " - " .. entry.endYear
elseif entry.startYear then
dateStr = entry.startYear .. " - Present"
end
-- Format as a table row
local row = mw.html.create('tr')
row:tag('th')
:attr('scope', 'row')
:addClass('infobox-label')
:wikitext("[[" .. entry.institution.link .. "|" .. entry.institution.text .. "]]")
local displayLink
if prefix == "Auxiliary Board for" then
displayLink = "[[Auxiliary Board#" .. entry.displayName .. "|" .. entry.displayName .. "]]"
elseif prefix == "Continental Board for" then
displayLink = "[[Continental Board for " .. entry.displayName .. "|" .. entry.displayName .. "]]"
elseif entry.institution.text == "UHJ member" or entry.institution.text == "ITC member" then
displayLink = ""
else
displayLink = "[[" .. entry.label .. "|" .. entry.displayName .. "]]"
end
if entry.institution.text == "UHJ member" or entry.institution.text == "ITC member" then
row:tag('td')
:addClass('infobox-data')
:wikitext(dateStr)
else
row:tag('td')
:addClass('infobox-data')
:wikitext(displayLink .. "<br>" .. dateStr)
end
table.insert(results, tostring(row))
-- Add category if applicable
if entry.institution.text == "NSA member" then
table.insert(results, "[[Category:Biographies of National Spiritual Assembly members]]")
elseif entry.institution.text == "UHJ member" then
table.insert(results, "[[Category:Biographies of Universal House of Justice members]]")
elseif entry.institution.text == "ITC member" then
table.insert(results, "[[Category:Biographies of International Teaching Centre members]]")
elseif entry.institution.text == "ABM" then
table.insert(results, "[[Category:Biographies of Auxiliary Board members]]")
elseif entry.institution.text == "Counsellor" then
table.insert(results, "[[Category:Biographies of Counsellors]]")
elseif entry.institution.text == "IBC member" then
table.insert(results, "[[Category:Biographies of International Bahá'í Council members]]")
elseif entry.institution.text == "Custodian" then
table.insert(results, "[[Category:Biographies of Custodians]]")
end
end
end
return table.concat(results, "")
end
function p.getDeathDate(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local deathDate = fetchPropertyValue(entity, 'P17')
-- Check if deathDate contains only a year (e.g., '+1980-00-00T00:00:00Z')
if deathDate and type(deathDate) == 'table' and deathDate.time and string.match(deathDate.time, "^%+%d%d%d%d%-00%-00") then
return string.sub(deathDate.time, 2, 5)
end
return deathDate and formatDate(deathDate, frame.args.format)
end
function p.getDeathPlace(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local deathPlaceId = fetchPropertyValue(entity, 'P18')
local lang = frame.args.lang or 'en'
return getItemLabel(deathPlaceId, lang)
end
function p.getDeathCountry(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
local deathPlaceId = fetchPropertyValue(entity, 'P18')
if not deathPlaceId then return nil end
local deathPlaceEntity = mw.wikibase.getEntity(deathPlaceId)
local countryId = fetchPropertyValue(deathPlaceEntity, 'P37')
local lang = frame.args.lang or 'en'
return getItemLabel(countryId, lang)
end
function p.getDeceasedAge(frame)
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then
return nil
end
local entity = mw.wikibase.getEntity(entityId)
local birthDate = fetchPropertyValue(entity, 'P16')
local deathDate = fetchPropertyValue(entity, 'P17')
-- Check if both birthDate and deathDate are available and contain full dates (year, month, day)
if not birthDate or not birthDate.time or birthDate.time:match("00%-00") then
return nil
end
if not deathDate or not deathDate.time or deathDate.time:match("00%-00") then
return nil
end
-- Parse dates
local birthYear, birthMonth, birthDay = birthDate.time:match("(%d%d%d%d)%-(%d%d)%-(%d%d)")
local deathYear, deathMonth, deathDay = deathDate.time:match("(%d%d%d%d)%-(%d%d)%-(%d%d)")
birthYear, birthMonth, birthDay = tonumber(birthYear), tonumber(birthMonth), tonumber(birthDay)
deathYear, deathMonth, deathDay = tonumber(deathYear), tonumber(deathMonth), tonumber(deathDay)
-- Calculate age
local age = deathYear - birthYear
if birthMonth > deathMonth or (birthMonth == deathMonth and birthDay > deathDay) then
age = age - 1
end
return age
end
function p.getSisterProjects(frame)
local s = {}
local entityId = mw.wikibase.getEntityIdForCurrentPage()
if not entityId then return nil end
local entity = mw.wikibase.getEntity(entityId)
if entity and entity.sitelinks then -- See if entity exists, and that it has sitelinks
for i, j in pairs(entity.sitelinks) do -- loop over all sitelinks
if mw.ustring.sub( j.site, mw.ustring.len(j.site) - 4 ) == 'works' then -- See which are to works
table.insert(s, '[[File:BW-favicon.png|16px| ]] [[:works:' .. j.title .. '|Works]]') -- Create a table of sites and sitelinks
elseif mw.ustring.sub( j.site, mw.ustring.len(j.site) - 4 ) == 'media' then -- See which are to media
table.insert(s, '[[File:Fav.png| ]] [[:c:' .. j.title .. '|Media]]') -- Create a table of sites and sitelinks
end
end
end
return table.concat(s, ' • ') -- Return as string
end
return p