Bahaipedia
Bahaipedia
Menu
About Bahaipedia
Ask a question
General help
Random page
Recent changes
In other projects
Tools
What links here
Related changes
Upload file
Special pages
Printable version
Permanent link
Page information
Module
Discussion
View history
Talk
Contributions
Create account
Log in
Navigation
About Bahaipedia
Ask a question
General help
Random page
Recent changes
In other projects
Learn more
Core topics
Bahá’í Faith
Central Figures
Teachings
Practices
Tools
What links here
Related changes
Upload file
Special pages
Printable version
Permanent link
Page information
Translations

Module:InfoboxWB

From Bahaipedia
Jump to:navigation, search
Module documentation[view] [edit] [history] [purge]

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.

Contents

  • 1 Functions
  • 2 Parameters
  • 3 Examples
    • 3.1 Basic
    • 3.2 Lang parameter
    • 3.3 Format parameter
  • 4 To do

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.

The above documentation is transcluded from Module:InfoboxWB/doc. (edit | history)
Editors can experiment in this module's sandbox (create | mirror) and testcases (create) pages.
Subpages of this module.

-- 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| ]]&nbsp;[[: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| ]]&nbsp;[[:c:' .. j.title .. '|Media]]')	-- Create a table of sites and sitelinks
			end
		end
	end
	return table.concat(s, ' • ')							-- Return as string
end

return p
Retrieved from "https://bahaipedia.org/index.php?title=Module:InfoboxWB&oldid=141719"
This page was last edited on 14 April 2025, at 08:33.
Text is available under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.
Privacy policy
About Bahaipedia
Disclaimers
Powered by MediaWiki