Module:Person
Appearance
Documentation for this module may be created at Module:Person/doc
-- ================================================================================
-- Module dependencies
-- ================================================================================
local cargo = mw.ext.cargo
local getArgs = require('Module:Arguments').getArgs -- for processing arguments
-- Utilities
local str = require("Module:String utilities")
-- Galleries
local gallery = require("Module:Gallery")
-- ================================================================================
-- Main table
-- ================================================================================
local p = {}
-- Builds a Cargo "OR" WHERE clause matching Full_name against each name in names.
local function build_or_conditions(names)
local conditions = {}
for _, name in ipairs(names) do
local sanitized = str.escape_string_for_sql(name)
table.insert(conditions, string.format("Full_name = '%s'", sanitized))
end
return table.concat(conditions, ' OR ')
end
-- Queries the Person table for the given names, falling back to Person_extra
-- for any names not found there. Person_extra holds people who are recorded
-- as data without getting their own full wiki page.
-- Returns a table keyed by Full_name -> row, containing only names that were found.
local function query_person_rows(name_array, fields)
local found_names = {}
local primary_results = cargo.query("Person", fields, { where = build_or_conditions(name_array) })
for _, entry in ipairs(primary_results) do
found_names[entry.Full_name] = entry
end
local missing_names = {}
for _, name in ipairs(name_array) do
if not found_names[name] then
table.insert(missing_names, name)
end
end
if #missing_names > 0 then
local backup_results = cargo.query("Person_extra", fields, {
where = build_or_conditions(missing_names)
})
for _, entry in ipairs(backup_results) do
found_names[entry.Full_name] = entry
end
end
return found_names
end
function p.get_person_gallery_modern(frame)
-- ========================================
-- Parse arguments
-- ========================================
local args = getArgs(frame)
local name_string = args.names or ""
local perrow = args.perrow or 6
-- Convert comma-delimited names to array
local name_array = {}
for value in string.gmatch(name_string, '([^,]+)') do
table.insert(name_array, mw.text.trim(value))
end
if #name_array == 0 then
return '<span class="gallery-error">No names provided!</span>'
end
-- ========================================
-- Query Person table (falling back to Person_extra)
-- ========================================
local fields = "Full_name, Image, Organizations, Position_titles"
local found_names = query_person_rows(name_array, fields)
-- ========================================
-- Build gallery items
-- ========================================
local placeholder = 'Face silhouette for no photo profiles.png'
local gallery_items = {}
for _, name in ipairs(name_array) do
local person = found_names[name]
-- Determine image
local image = placeholder
if person and person.Image and person.Image ~= '' then
image = str.file_title(person.Image)
end
-- Simple caption: just the name as a link
local caption = string.format("[[%s|%s]]", name, name)
table.insert(gallery_items, {
image = image,
link = name,
caption = caption
})
end
local gallery_output = gallery.build_modern_gallery(gallery_items, {
widths = "175px",
perrow = perrow,
show_captions = "always"
})
return frame:preprocess(gallery_output)
end
-- ================================================================================
-- Get person gallery
-- ================================================================================
function p.get_person_gallery(frame)
-- ========================================
-- Parse arguments
-- ========================================
local args = getArgs(frame)
local gallery_mode = args.gallery_mode or "packed"
local name_string = args.names or ""
local name_array = {}
for value in string.gmatch(name_string, '([^,]+)') do
table.insert(name_array, mw.text.trim(value))
end
if #name_array == 0 then
return '<span class="gallery-error">No names provided!</span>'
end
-- ========================================
-- Query Person table (falling back to Person_extra)
-- ========================================
local placeholder_image = 'Face silhouette for no photo profiles.png'
local fields = "Full_name, Image, Organizations, Position_titles"
local found_names = query_person_rows(name_array, fields)
-- ========================================
-- Build gallery items
-- ========================================
local gallery_items = {}
for _, name in ipairs(name_array) do
local person = found_names[name]
local image = placeholder_image
if person and person.Image and person.Image ~= '' then
image = str.file_title(person.Image)
end
local organizations = (person and person.Organizations) or "Unknown organization"
local position_titles = (person and person.Position_titles) or "Unknown position"
local caption = string.format("%s<br>%s<br>%s", name, organizations, position_titles)
table.insert(gallery_items, { image = image, caption = caption })
end
-- ========================================
-- Render through Module:Gallery instead of hand-built wikitext
-- ========================================
local gallery_wikitext = gallery.build_gallery(gallery_items, { mode = gallery_mode, heights = "200" })
return frame:preprocess(gallery_wikitext)
end
-- ================================================================================
-- Create a person bio box (with robust checks and meaningful errors)
-- ================================================================================
function p.get_person_bio_box(frame)
-- --------------------------------------------------------------------------
-- 1. Validate frame and arguments
-- --------------------------------------------------------------------------
if frame == nil then
return '<span style="color: red;">Error: No frame passed to get_person_bio_box.</span>'
end
local ok, args = pcall(getArgs, frame)
if not ok then
return string.format('<span style="color: red;">Error retrieving template arguments: %s</span>', args or "unknown error")
end
local title = mw.title.getCurrentTitle() and mw.title.getCurrentTitle().text or "(no title)"
local name = args.name or title or ""
if name == "" then
return '<span style="color: red;">Error: No name provided and current page title is empty.</span>'
end
-- --------------------------------------------------------------------------
-- 2. Run Cargo query
-- --------------------------------------------------------------------------
local tables = "Person"
local fields = "Full_name, Image, Position_titles, Bio"
local where = string.format('Full_name = "%s"', mw.text.trim(name))
local cargo_results
local success, err = pcall(function()
cargo_results = mw.ext.cargo.query(tables, fields, { where = where })
end)
if not success then
return string.format('<span style="color: red;">Error querying Cargo: %s</span>', err or "unknown")
end
if not cargo_results or #cargo_results < 1 then
return string.format('<span style="color: red;">No Cargo record found for "%s".</span>', name)
end
local row = cargo_results[1]
-- --------------------------------------------------------------------------
-- 3. Prepare values safely
-- --------------------------------------------------------------------------
local image = row.Image
if not image or image == "" then
image = "Face silhouette for no photo profiles.png"
end
if str and str.add_file_prefix_gentle then
local ok2, prefixed = pcall(str.add_file_prefix_gentle, image)
if ok2 and prefixed then image = prefixed end
end
local position_titles = args.position_title or row.Position_titles or ""
local bio_text = row.Bio or ""
-- --------------------------------------------------------------------------
-- 4. Build HTML structure
-- --------------------------------------------------------------------------
local container = mw.html.create('div'):addClass('person-photo-box')
-- Header
local header_text
if position_titles ~= "" then
header_text = string.format('[[%s|%s - %s]]', name, name, position_titles)
else
header_text = string.format('[[%s|%s]]', name, name)
end
container:tag('div')
:addClass('person-photo-header')
:wikitext(header_text)
-- Content wrapper
local contentWrapper = mw.html.create('div'):addClass('content-wrapper')
local imageDiv = mw.html.create('div')
:addClass('person-photo-content')
:wikitext(string.format('[[%s|link=%s]]', image, name))
local textDiv = mw.html.create('div')
:addClass('person-photo-text')
:wikitext(bio_text)
contentWrapper:node(imageDiv):node(textDiv)
container:node(contentWrapper)
-- --------------------------------------------------------------------------
-- 5. Return safely
-- --------------------------------------------------------------------------
return tostring(container)
end
-- ================================================================================
-- Get person photo
-- ================================================================================
local function get_person_photo(frame)
local args = getArgs(frame)
local title = mw.title.getCurrentTitle().text
local name = args.name or title
-- cargo query to retrieve user image
local tables = "Person"
local fields = "Full_name, Image"
local cargo_args = {
where = string.format('Full_name = "%s"', name)
}
local cargo_results = cargo.query(tables, fields, cargo_args)
-- extract image name
local image = cargo_results[1].Image
-- add file prefix if needed
image = str.add_file_prefix_gentle(image)
if cargo_results and #cargo_results > 0 then
-- return user bio
return "[[" .. image .. "]]"
else
-- return error message in red
return string.format('<span style="color: red;">%s</span>', "Can't find this name in the Cargo database!")
end
end
p.get_person_photo = get_person_photo
-- ================================================================================
-- Retrieve a Person biography
-- ================================================================================
local function biography(frame)
local args = getArgs(frame)
local title = mw.title.getCurrentTitle().text
local name = args.name or title
-- cargo query to retrieve user bio
local tables = "Person"
local fields = "Full_name, Bio"
local cargo_args = {
where = string.format('Full_name = "%s"', name)
}
local cargo_results = cargo.query(tables, fields, cargo_args)
if cargo_results and #cargo_results > 0 then
-- return user bio
return cargo_results[1]["Bio"]
else
-- return error message in red
return string.format('<span style="color: red;">%s</span>', "Can't find this name in the Cargo database!")
end
end
p.biography = biography
return p