|
local p = {}
local PBD = require('Module:PBD')
local PBDIB = require('Module:PornBaseDataIB')
local BioboxUnits = require('Module:BioboxUnits')
local GetBirthDate = require('Module:GetBirthDate')
local BirthDateAndAge = require('Module:Birth date and age')
local Pornbasedata = require('Module:Pornbasedata')
local CategoryMapping = require('Module:BioboxCategoryMapping')
local BioboxPersonal = require('Module:BioboxPersonal')
local BioboxBody = require('Module:BioboxBody')
local BioboxPersonalPages = require('Module:BioboxPersonalPages')
local BioboxDatabases = require('Module:BioboxDatabases')
local BioboxSharing = require('Module:BioboxSharing')
local ALIAS_TO_PRIMARY = {}
return normalized
end
local function isPositive(value)
if isEmpty(value) then return false end
value = tostring(value):lower()
local positiveValues = {
['yes'] = true,
['y'] = true,
['ya'] = true,
['yep'] = true,
['true'] = true,
['1'] = true
}
return positiveValues[value] or false
end
return tonumber(value) ~= nil
end
local POSITIVE_ONLY_FIELDS = {
['tattoo'] = true
}
local function shouldDisplayField(fieldName, value)
fpbd = "ALL"
})
end
local function getPBDValue(propertyId, args, directValue)
if isEmpty(directValue) then
return PBD._property{propertyId, 'raw', 'multilanguage', ['eid'] = args.qid}
end
return directValue
end
local function getImage(args)
if not isEmpty(args.image) then
return string.format('[[File:%s|256px]]', args.image)
end
local qid = args.qid
if isEmpty(qid) then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
if qid then
local image = PBDIB._getValue({
[1] = "P470",
qid = qid,
rank = "best",
name = "image",
fpbd = "ALL",
osd = "no",
noicon = "yes",
maxvals = 1
})
if not isEmpty(image) then
return string.format([[%s
<div style="text-align: center;">%s</div>]],
mw.ustring.format(
'[[File:%s|256px]]',
image
),
PBDIB._getValue({
qid = qid,
fpbd = "ALL",
osd = "no",
noicon = "y",
qual = "P523",
qualsonly = "yes",
maxvals = 1
}) or ''
)
end
end
return '[[File:NoImageAvailable.png|256px|link=PBC:Images]]'
end
local State = {}
function State:new()
local state = {}
setmetatable(state, self)
self.__index = self
return state
end
local function calculateAge(birthYear, birthMonth, birthDay, deathYear, deathMonth, deathDay)
birthYear = tonumber(birthYear)
deathYear = tonumber(deathYear)
birthMonth = tonumber(birthMonth)
deathMonth = tonumber(deathMonth)
birthDay = tonumber(birthDay)
deathDay = tonumber(deathDay)
if birthYear and deathYear and birthYear > 0 and deathYear > 0 then
local age = deathYear - birthYear
if birthMonth and deathMonth then
if deathMonth < birthMonth or
(deathMonth == birthMonth and birthDay and deathDay and deathDay < birthDay) then
age = age - 1
end
end
if age >= 0 then
return string.format(" (aged %d)", age)
end
end
return ""
end
function State:formatBirthDate(args, rowIndex)
local section = {}
local birthDay = args.birth_day ~= "" and args.birth_day or nil
local birthMonth = args.birth_month ~= "" and args.birth_month or nil
local birthYear = args.birth_year ~= "" and args.birth_year or nil
local birthRef = args.birth_ref
local hasDeathDate = false
if (args.death_year and args.death_year ~= "")
or (args.death_month and args.death_month ~= "")
or (args.death_day and args.death_day ~= "")
then
hasDeathDate = true
elseif args.qid then
local deathDate = PBD._property{
[1] = 'P247',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
hasDeathDate = deathDate and deathDate ~= ""
end
if not (birthDay or birthMonth or birthYear) and args.qid then
local birthDate = PBD._property{
[1] = 'P9',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if birthDate and birthDate ~= "" then
local frame = mw.getCurrentFrame()
birthDay = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'day'
}})
birthMonth = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'month'
}})
birthYear = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'year'
}})
birthDay = birthDay ~= "" and tonumber(birthDay) or nil
birthMonth = birthMonth ~= "" and tonumber(birthMonth) or nil
birthYear = birthYear ~= "" and tonumber(birthYear) or nil
end
end
if not (birthDay or birthMonth or birthYear) then
return {}, rowIndex
end
local birthDateDisplay = ""
local categories = {}
local isMainNamespace = mw.title.getCurrentTitle().namespace == 0
if birthMonth and birthDay and birthYear then
local frame = mw.getCurrentFrame()
local success, result = pcall(function()
local monthTime = {year = 2000, month = tonumber(birthMonth), day = 1}
local monthName = os.date('%B', os.time(monthTime))
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s_%s_birthdays]]", monthName, birthDay)
categories[#categories + 1] = string.format("[[Category:%s_births]]", birthYear)
end
if hasDeathDate then
local basicDate = string.format("[[:Category:%s %s birthdays|%s %s]] [[:Category:%s births|%s]]",
monthName, birthDay,
birthDay, monthName,
birthYear, birthYear
)
local childFrame = frame:newChild{
args = { birthYear, birthMonth, birthDay }
}
local zodiacResult = BirthDateAndAge.main(childFrame)
local zodiacPart = zodiacResult:match("<br>Astrology:.*$")
return basicDate .. (zodiacPart or "")
else
local childFrame = frame:newChild{
args = { birthYear, birthMonth, birthDay }
}
return BirthDateAndAge.main(childFrame)
end
end)
if success and result ~= "" then
birthDateDisplay = result .. table.concat(categories, "")
section[#section + 1] = string.format('|-\n! style="%s %s" | \'\'\'Birth:\'\'\'\n| style="text-align:left;" | %s',
self:getRowStyle(rowIndex),
STYLES.LABEL,
birthDateDisplay
)
rowIndex = rowIndex + 1
return section, rowIndex
end
local monthTime = {year = 2000, month = tonumber(birthMonth), day = 1}
local monthName = os.date('%B', os.time(monthTime))
birthDateDisplay = string.format("[[:Category:%s %s birthdays|%s %s]] [[:Category:%s births|%s]]",
monthName, birthDay,
birthDay, monthName,
birthYear, birthYear
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s_%s_birthdays]]", monthName, birthDay)
categories[#categories + 1] = string.format("[[Category:%s_births]]", birthYear)
end
local zodiacSuccess, zodiacResult = pcall(function()
return BirthDateAndAge.main{[1]=birthYear, [2]=birthMonth, [3]=birthDay}
end)
if zodiacSuccess then
local zodiacPart = zodiacResult:match("<br>Astrology:.*$")
if zodiacPart then
birthDateDisplay = birthDateDisplay .. zodiacPart
end
end
elseif birthMonth and birthYear then
local ok, monthName
local monthTime = {year = 2000, month = tonumber(birthMonth), day = 1}
ok, monthName = pcall(os.date, '%B', os.time(monthTime))
if ok and monthName then
birthDateDisplay = string.format("[[:Category:%s birthdays|%s]] [[:Category:%s births|%s]]%s",
monthName,
monthName,
birthYear,
birthYear,
not hasDeathDate and string.format(" (≈%d years)", os.date('%Y') - birthYear) or ""
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s births]]", birthYear)
categories[#categories + 1] = string.format("[[Category:%s birthdays]]", monthName)
end
end
elseif birthYear then
local appendAge = not hasDeathDate and string.format(" (≈%d years)", os.date('%Y') - birthYear) or ""
birthDateDisplay = string.format("[[:Category:%s births|%s]]%s",
birthYear,
birthYear,
appendAge
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s births]]", birthYear)
end
elseif birthMonth and birthDay then
local monthTime = {year = 2000, month = birthMonth, day = 1}
local ok, monthName = pcall(os.date, '%B', os.time(monthTime))
if ok and monthName then
birthDateDisplay = string.format("[[:Category:%s %s birthdays|%s %s]]",
monthName, birthDay,
monthName, birthDay
)
if isMainNamespace then
categories[#categories + 1] = "[[Category:Birth year needed]]"
categories[#categories + 1] = string.format("[[Category:%s_%s_birthdays]]", monthName, birthDay)
end
end
do
local frame = mw.getCurrentFrame()
local childFrame = frame:newChild{
args = {
[1] = "",
[2] = birthMonth,
[3] = birthDay
}
}
local success, zodiacResult = pcall(BirthDateAndAge.main, childFrame)
if success and type(zodiacResult) == "string" and zodiacResult ~= "" then
local zodiacPart = zodiacResult:match("<br>Astrology:.*$")
if zodiacPart then
birthDateDisplay = birthDateDisplay .. zodiacPart
end
end
end
end
if birthDateDisplay ~= "" then
if birthRef then
birthDateDisplay = birthDateDisplay .. birthRef
end
section[#section + 1] = string.format('|-\n! style="%s %s" | \'\'\'Birth:\'\'\'\n| style="text-align:left;" | %s',
self:getRowStyle(rowIndex),
STYLES.LABEL,
birthDateDisplay .. table.concat(categories, '')
)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatPlaceOfBirth(args, rowIndex)
local section = {}
local categories = {}
local placeOfBirth = args.place_of_birth
if isEmpty(placeOfBirth) and args.qid then
local birthplaces = {}
local entity = mw.wikibase.getEntity(args.qid)
if entity and entity.claims and entity.claims.P20 then
for _, statement in pairs(entity.claims.P20) do
if statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id then
local placeId = statement.mainsnak.datavalue.value.id
local sitelink = mw.wikibase.getSitelink(placeId)
if sitelink and mw.ustring.match(sitelink, '^' .. mw.site.namespaces[14].name .. ':') then
table.insert(categories, '[[' .. sitelink .. ']]')
end
end
end
end
local frame = mw.getCurrentFrame()
local newFrame = frame:newChild{
args = {
property = 'P20',
entityId = args.qid,
references = 'yes',
separator = ', '
}
}
local formatResult = Pornbasedata.formatProperty(newFrame)
if not isEmpty(formatResult) then
placeOfBirth = formatResult
end
end
if not isEmpty(placeOfBirth) then
local rowStyle = self:getRowStyle(rowIndex)
section[#section + 1] = string.format(
'|-\n! style="%s %s" | \'\'\'Place of birth:\'\'\'\n| style="%s text-align:left;" | %s%s',
rowStyle,
STYLES.LABEL,
rowStyle,
placeOfBirth,
table.concat(categories, '')
)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
local function processCountryValue(value)
if not value then return nil end
value = mw.text.trim(value)
if value == '' then return nil end
value = value:gsub('^{{', ''):gsub('}}$', '')
value = mw.text.trim(value)
return string.format('{{flagcountry|%s}}', value)
end
function State:formatBirthCountry(args, rowIndex)
local section = {}
local birthCountry = args.birth_country
if isEmpty(birthCountry) and args.qid then
birthCountry = PBD._property{
[1] = 'P144',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(birthCountry) then
birthCountry = birthCountry:match("^[^,\n]+")
end
end
local displayValue = processCountryValue(birthCountry)
if displayValue then
local frame = mw.getCurrentFrame()
local expandedDisplayValue = frame:preprocess(displayValue)
section[#section + 1] = self:formatField(
"Country of birth:",
expandedDisplayValue,
"birth_country",
rowIndex
)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatCitizenship(args, rowIndex)
local section = {}
local citizenshipValues = {}
if not isEmpty(args.citizenship) then
table.insert(citizenshipValues, args.citizenship)
end
for i = 2, 4 do
local param = "citizenship" .. i
if not isEmpty(args[param]) then
table.insert(citizenshipValues, args[param])
end
end
if #citizenshipValues == 0 and args.qid then
local pbdValues = PBD._properties{
[1] = 'P133',
raw = true,
multilanguage = true,
sep = '\n',
['eid'] = args.qid
}
if not isEmpty(pbdValues) then
for value in pbdValues:gmatch("[^,\n]+") do
table.insert(citizenshipValues, mw.text.trim(value))
end
end
end
local displayValues = {}
for _, value in ipairs(citizenshipValues) do
local processed = processCountryValue(value)
if processed then
table.insert(displayValues, processed)
end
end
if #displayValues > 0 then
local concatenated = table.concat(displayValues, "<br>")
local frame = mw.getCurrentFrame()
local expandedDisplayValue = frame:preprocess(concatenated)
section[#section + 1] = self:formatField(
"Citizenship:",
expandedDisplayValue,
"citizenship",
rowIndex
)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatDeathDate(args, rowIndex)
local section = {}
local deathDay = args.death_day ~= "" and args.death_day or nil
local deathMonth = args.death_month ~= "" and args.death_month or nil
local deathYear = args.death_year ~= "" and args.death_year or nil
local deathRef = args.death_ref
local birthYear = args.birth_year ~= "" and args.birth_year or nil
local birthMonth = args.birth_month ~= "" and args.birth_month or nil
local birthDay = args.birth_day ~= "" and args.birth_day or nil
if deathYear and tonumber(deathYear) and tonumber(deathYear) <= 0 then
deathYear = nil
end
local hasPBDDeathDate = false
if not (deathDay or deathMonth or deathYear) and args.qid then
local deathDate = PBD._property{
[1] = 'P247',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if deathDate and deathDate ~= "" then
hasPBDDeathDate = true
local frame = mw.getCurrentFrame()
local pdbDeathDay = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P247',
[2] = 'day'
}})
local pdbDeathMonth = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P247',
[2] = 'month'
}})
local pdbDeathYear = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P247',
[2] = 'year'
}})
if pdbDeathDay ~= "" then deathDay = tonumber(pdbDeathDay) end
if pdbDeathMonth ~= "" then deathMonth = tonumber(pdbDeathMonth) end
if pdbDeathYear ~= "" then deathYear = tonumber(pdbDeathYear) end
if not birthYear or not birthMonth or not birthDay then
local birthDate = PBD._property{
[1] = 'P9',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if birthDate and birthDate ~= "" then
if not birthYear then
local pdbBirthYear = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'year'
}})
if pdbBirthYear ~= "" then birthYear = tonumber(pdbBirthYear) end
end
if not birthMonth then
local pdbBirthMonth = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'month'
}})
if pdbBirthMonth ~= "" then birthMonth = tonumber(pdbBirthMonth) end
end
if not birthDay then
local pdbBirthDay = GetBirthDate.property(frame:newChild{ args = {
[1] = 'P9',
[2] = 'day'
}})
if pdbBirthDay ~= "" then birthDay = tonumber(pdbBirthDay) end
end
end
end
end
end
if not (deathDay or deathMonth or deathYear) and not hasPBDDeathDate then
return {}, rowIndex
end
local deathDateDisplay = ""
local categories = {}
local isMainNamespace = mw.title.getCurrentTitle().namespace == 0
if isMainNamespace then
categories[#categories + 1] = "[[Category:Dead people]]"
end
local ageAtDeath = calculateAge(birthYear, birthMonth, birthDay, deathYear, deathMonth, deathDay)
if deathMonth and deathDay and deathYear then
local ok, monthName = pcall(os.date, '%B', os.time({year = 2000, month = tonumber(deathMonth), day = 1}))
if ok and monthName then
deathDateDisplay = string.format("[[:Category:%s %s deaths|%s %s]] [[:Category:%s deaths|%s]]%s",
monthName, deathDay,
deathDay, monthName,
deathYear, deathYear,
ageAtDeath
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s deaths]]", deathYear)
categories[#categories + 1] = string.format("[[Category:%s_%s_deaths]]", monthName, deathDay)
end
end
elseif deathMonth and deathYear then
local ok, monthName = pcall(os.date, '%B', os.time({year = 2000, month = tonumber(deathMonth), day = 1}))
if ok and monthName then
deathDateDisplay = string.format("[[:Category:%s deaths|%s]] [[:Category:%s deaths|%s]]%s",
monthName,
monthName,
deathYear, deathYear,
ageAtDeath
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s deaths]]", deathYear)
categories[#categories + 1] = string.format("[[Category:%s deaths]]", monthName)
end
end
elseif deathYear then
deathDateDisplay = string.format("[[:Category:%s deaths|%s]]%s",
deathYear, deathYear,
ageAtDeath
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s deaths]]", deathYear)
end
elseif deathMonth and deathDay then
local ok, monthName = pcall(os.date, '%B', os.time({year = 2000, month = tonumber(deathMonth), day = 1}))
if ok and monthName then
deathDateDisplay = string.format("[[:Category:%s %s deaths|%s %s]]",
monthName, deathDay,
monthName, deathDay
)
if isMainNamespace then
categories[#categories + 1] = string.format("[[Category:%s_%s_deaths]]", monthName, deathDay)
end
end
end
if deathDateDisplay ~= "" then
if deathRef then
deathDateDisplay = deathDateDisplay .. deathRef
end
section[#section + 1] = string.format('|-\n! style="%s %s" | \'\'\'Died:\'\'\'\n| style="text-align:left;" | %s',
self:getRowStyle(rowIndex),
STYLES.LABEL,
deathDateDisplay .. table.concat(categories, '')
)
rowIndex = rowIndex + 1
local deathLocation = nil
if args.death_location and args.death_location ~= "" then
deathLocation = args.death_location
elseif args.qid then
deathLocation = PBD._property{[1] = 'P23', raw = true, multilanguage = true, ['eid'] = args.qid}
end
if not isEmpty(deathLocation) then
section[#section + 1] = string.format('|-\n! style="%s %s" | \'\'\'Place of death:\'\'\'\n| style="text-align:left;" | %s',
self:getRowStyle(rowIndex),
STYLES.LABEL,
deathLocation
)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
end
local functionState getHeight(frame,= args){}
local height = args.height
if BioboxUnits.isValidHeight(height) then
return BioboxUnits.formatHeight(frame, height, {})
end
local pbdHeight = PBD._property{[1] = 'P156', raw = true, multilanguage = true, ['eid'] = args.qid}
local heightNum = BioboxUnits.extractNumber(pbdHeight)
if heightNum then
return BioboxUnits.formatHeight(frame, heightNum, {})
end
return 'N/A'
end
local function getWeightState:new(frame, args)
local weightstate = args.weight{}
setmetatable(state, self)
if BioboxUnits.isValidWeight(weight) then
self.__index = self
return BioboxUnits.formatWeight(frame, weight, {})
state.STYLES = STYLES
end
return state
local pbdWeight = PBD._property{[1] = 'P159', raw = true, multilanguage = true, ['eid'] = args.qid}
local weightNum = BioboxUnits.extractNumber(pbdWeight)
if weightNum then
return BioboxUnits.formatWeight(frame, weightNum, {})
end
return 'N/A'
end
local function getPenisSize(frame, args)
frame = frame or mw.getCurrentFrame()
local penisSize = args['penis_size'] or args['penis size']
if not isEmpty(penisSize) then
local childArgs = {}
childArgs[1] = tostring(penisSize)
childArgs["break"] = "y"
childArgs["linkspan"] = "y"
return BioboxUnits.formatPenisSize(frame:newChild{args = childArgs})
end
local pbdPenisSize = PBD._property{[1] = 'P161', raw = true, multilanguage = true, ['eid'] = args.qid}
if not isEmpty(pbdPenisSize) then
local childArgs = {}
childArgs[1] = tostring(pbdPenisSize)
childArgs["break"] = "y"
childArgs["linkspan"] = "y"
return BioboxUnits.formatPenisSize(frame:newChild{args = childArgs})
end
return 'N/A'
end
return result
end
function State:formatEthnicity(args, rowIndex)
local section = {}
local ethnicityValues = self:collectNumberedParams(args, "ethnicity")
if #ethnicityValues == 0 and args.qid then
local pbdValue = PBD._properties{
[1] = 'P136',
raw = true,
normal = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(ethnicityValues, pbdValue)
end
end
if #ethnicityValues > 0 then
local displayValue = {}
for _, eth in ipairs(ethnicityValues) do
local ethnicities = self:splitByComma(eth)
for _, e in ipairs(ethnicities) do
if #displayValue > 0 then
table.insert(displayValue, ", ")
end
e = mw.text.trim(e):gsub("^%l", string.upper)
local result = string.format("[[:Category:%s|%s]]", e, e)
if mw.title.getCurrentTitle().namespace == 0 then
result = result .. string.format("[[Category:%s]]", e)
end
table.insert(displayValue, result)
end
end
section[#section + 1] = self:formatField("Ethnicity:",
table.concat(displayValue, ""),
"ethnicity",
rowIndex)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatNationality(args, rowIndex)
local section = {}
local nationalityValues = self:collectNumberedParams(args, "nationality")
if #nationalityValues == 0 and args.qid then
local pbdValue = PBD._properties{
[1] = 'P131',
raw = true,
normal = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(nationalityValues, pbdValue)
end
end
if #nationalityValues > 0 then
local displayValue = {}
for _, nat in ipairs(nationalityValues) do
local nationalities = self:splitByComma(nat)
for _, n in ipairs(nationalities) do
if #displayValue > 0 then
table.insert(displayValue, ", ")
end
n = mw.text.trim(n):gsub("^%l", string.upper)
local result = string.format("[[:Category:%s|%s]]", n, n)
if mw.title.getCurrentTitle().namespace == 0 then
result = result .. string.format("[[Category:%s]]", n)
end
table.insert(displayValue, result)
end
end
section[#section + 1] = self:formatField("Nationality:",
table.concat(displayValue, ""),
"nationality",
rowIndex)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatCareer(args, rowIndex)
local section = {}
local isMainNamespace = mw.title.getCurrentTitle().namespace == 0
local careerstart = args.careerstart
if isEmpty(careerstart) and args.qid then
careerstart = PBD._property{
[1] = 'P153',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(careerstart) then
local result = string.format("[[:Category:%s career start|%s]]", careerstart, careerstart)
if isMainNamespace then
result = result .. string.format("[[Category:%s career start]]", careerstart)
end
section[#section + 1] = self:formatField("Career Start:",
result,
"careerstart",
rowIndex)
rowIndex = rowIndex + 1
end
local career = args.career
if isEmpty(career) and args.qid then
career = PBD._property{
[1] = 'P154',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
local isActive = false
if not isEmpty(career) then
local statusMap = {
["A"] = {text = "Active", category = "Currently Active Pornstars", class = "careerstatusactive"},
["AS"] = {text = "Active (Straight Only)", category = "Currently Active Pornstars (Straight Only)", class = "careerstatusactive"},
["R"] = {text = "Retired", category = "Retired Pornstars", class = "careerstatusretired"},
["ACTIVE"] = {text = "Active", category = "Currently Active Pornstars", class = "careerstatusactive"},
["RETIRED"] = {text = "Retired", category = "Retired Pornstars", class = "careerstatusretired"}
}
career = career:upper()
local status = statusMap[career]
if status then
isActive = (career == "A" or career == "AS" or career == "ACTIVE")
local displayValue = string.format('<span class="%s">[[:Category:%s|%s]]</span>',
status.class,
status.category,
status.text
)
if isMainNamespace then
displayValue = displayValue .. string.format("[[Category:%s]]",
status.category
)
end
section[#section + 1] = self:formatField("Career Status:",
displayValue,
"career",
rowIndex)
rowIndex = rowIndex + 1
end
end
if not isActive then
local careerend = args.careerend
if isEmpty(careerend) and args.qid then
careerend = PBD._property{
[1] = 'P155',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(careerend) then
local result = string.format("[[:Category:%s career end|%s]]", careerend, careerend)
if isMainNamespace then
result = result .. string.format("[[Category:%s career end]]", careerend)
end
section[#section + 1] = self:formatField("Career End:",
result,
"careerend",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
rowStyle,
value)
end
function State:getPBDCategories(args)
if mw.title.getCurrentTitle().namespace ~= 0 then
return {}
end
local categories = {}
local qid = args.qid
if isEmpty(qid) then
qid = mw.wikibase.getEntityIdForCurrentPage()
end
if isEmpty(qid) then
return {}
end
local birthplaceProps = mw.wikibase.getBestStatements(qid, "P20")
if birthplaceProps and #birthplaceProps > 0 then
for _, statement in pairs(birthplaceProps) do
if statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id then
local placeId = statement.mainsnak.datavalue.value.id
local sitelink = mw.wikibase.getSitelink(placeId)
if sitelink then
sitelink = sitelink:gsub("^" .. mw.site.namespaces[14].name .. ":", "")
table.insert(categories, sitelink)
end
end
end
end
local birthCountryProps = mw.wikibase.getBestStatements(qid, "P144")
if birthCountryProps and #birthCountryProps > 0 then
for _, statement in pairs(birthCountryProps) do
if statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id then
local countryId = statement.mainsnak.datavalue.value.id
local sitelink = mw.wikibase.getSitelink(countryId)
if sitelink then
sitelink = sitelink:gsub("^" .. mw.site.namespaces[14].name .. ":", "")
table.insert(categories, sitelink)
end
end
end
end
local occupationProps = mw.wikibase.getBestStatements(qid, "P124")
if occupationProps and #occupationProps > 0 then
for _, statement in pairs(occupationProps) do
if statement.mainsnak and
statement.mainsnak.datavalue and
statement.mainsnak.datavalue.value and
statement.mainsnak.datavalue.value.id then
local occupationId = statement.mainsnak.datavalue.value.id
local sitelink = mw.wikibase.getSitelink(occupationId)
if sitelink then
sitelink = sitelink:gsub("^" .. mw.site.namespaces[14].name .. ":", "")
table.insert(categories, sitelink)
end
end
end
end
return categories
end
function State:formatPersonalSection(args, title)
local section = {}
local rowIndex = 1
if not args.qid or args.qid == "" then
args.qid = mw.wikibase.getEntityIdForCurrentPage()
end
section[#section + 1] = string.format('{| %s', STYLES.INFOBOX)
local name = args.name
if isEmpty(name) then
name = getPBDValue('P7', args)
if isEmpty(name) then
name = title
end
end
section[#section + 1] = string.format('|-\n! colspan="2" %s | \'\'\'%s\'\'\'', STYLES.HEADER, name)
local imageHtml = getImage(args)
local imageCaption = not isEmpty(args.imagecaption) and
string.format('<br>\'\'%s\'\'', args.imagecaption) or ''
section[#section + 1] = string.format('|-\n| colspan="2" style="text-align:center;" | %s%s',
imageHtml, imageCaption)
section[#section + 1] = string.format('|-\n! colspan="2" %s | \'\'\'Personal\'\'\'', STYLES.SECTION_HEADER)
local personalFields = {
{label = 'Birth name:', prop = 'P5', param = 'real_name'},
{label = 'Legal name:', prop = 'P753', param = 'legal_name'},
{label = 'Native name:', prop = 'P13', param = 'native_name'},
{label = 'Name in kana:', prop = 'P480', param = 'name_in_kana'},
{label = 'Aliases:', prop = 'P140', param = 'alias'},
{label = 'Nicknames:', prop = 'P363', param = 'nicknames'}
}
for _, field in ipairs(personalFields) do
local value = getPBDValue(field.prop, args, args[field.param])
local fieldLine = self:formatField(field.label, value, field.param, rowIndex)
if fieldLine ~= '' then
section[#section + 1] = fieldLine
rowIndex = rowIndex + 1
end
end
local birthSection, newRowIndex = self:formatBirthDate(args, rowIndex)
for _, line in ipairs(birthSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local placeOfBirthSection, newRowIndex = self:formatPlaceOfBirth(args, rowIndex)
for _, line in ipairs(placeOfBirthSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local birthCountrySection, newRowIndex = self:formatBirthCountry(args, rowIndex)
for _, line in ipairs(birthCountrySection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local citizenshipSection, newRowIndex = self:formatCitizenship(args, rowIndex)
for _, line in ipairs(citizenshipSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local deathSection, newRowIndex = self:formatDeathDate(args, rowIndex)
for _, line in ipairs(deathSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local ethnicitySection, newRowIndex = self:formatEthnicity(args, rowIndex)
for _, line in ipairs(ethnicitySection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local nationalitySection, newRowIndex = self:formatNationality(args, rowIndex)
for _, line in ipairs(nationalitySection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local careerSection, newRowIndex = self:formatCareer(args, rowIndex)
for _, line in ipairs(careerSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
return table.concat(section, '\n'), rowIndex
end
end
if featureType == 'ass_type' then
for _, value in ipairs(values) do
iflocal valuefoundMappings then= {}
local featureshasMainType = self:splitByComma(value)false
for _, feature in ipairs(features) do
for _, value in ipairs(values) do
feature = mw.text.trim(feature):lower()
if value then
local mapping = CategoryMapping.MAPPINGS[featureType][feature]
local features = self:splitByComma(value)
iffor mapping_, andfeature notin addedCategories[mapping.category]ipairs(features) thendo
iffeature #displayValues= > 0 thenmw.text.trim(feature):lower()
table.insert(displayValues, ", ")
end
localfor result_, =mapping string.formatin ipairs("CategoryMapping.MAPPINGS[[:Category:%s|%sfeatureType]]",) do
for _, alias in ipairs(mapping.category,aliases) do
mapping.display if feature == alias:lower() then
) local isMainSize = mapping.priority >= 1 and mapping.priority <= 3
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
addedCategories[mapping.category] = true
end
end
end
end
if #displayValues > 0 then
return table.concat(displayValues)
end
return nil
end
if (not isMainSize or not hasMainType) and not addedCategories[mapping.category] then
function State:formatFeature(args, featureType, rowIndex)
table.insert(foundMappings, mapping)
local section = {}
addedCategories[mapping.category] = true
local values = {}
if isMainSize then
hasMainType = true
local baseNames = {
hair = {'hair', 'hair_color'}, end
end
eye_color = {'eye color', 'eye_color', 'eyes', 'eye'},
end
body_type = {'body type', 'body_type', 'body'},
skin = {'skin', 'skin_color', 'skincomplexion'},
foreskin = {'foreskin'}
}
for _, baseName in ipairs(baseNames[featureType]) do
if not isEmpty(args[baseName]) then
table.insert(values, args[baseName])
break
end
end
local found = false
for i = 2, 10 do
for _, baseName in ipairs(baseNames[featureType]) do
local param = baseName .. tostring(i)
if not isEmpty(args[param]) then
table.insert(values, args[param])
found = true
break
end
end
if not found then
break
end
found = false
end
if #values == 0 and args.qid then
local success, properties = pcall(function()
return PBD._properties{
[1] = CategoryMapping.PROPERTY_IDS[featureType],
raw = false,
multilanguage = true,
sep = '\n',
['eid'] = args.qid
}
end)
if success and not isEmpty(properties) then
for value in properties:gmatch("[^,\n]+") do
table.insert(values, mw.text.trim(value))
end
end
end
local displayValue = self:formatFeatureList(values, featureType)
if displayValue then
section[#section + 1] = self:formatField(CategoryMapping.LABELS[featureType],
displayValue,
featureType,
rowIndex)
rowIndex = rowIndex + 1
end
return section, rowIndex
end
function State:formatHair(args, rowIndex)
local section = {}
local hairValues = self:collectNumberedParams(args, "hair_color")
if #hairValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P162',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(hairValues, pbdValue)
end
end
if #hairValues > 0 then
local displayValue = self:formatFeatureList(hairValues, 'hair')
if displayValue then
section[#section + 1] = self:formatField("Hair:",
displayValue,
"hair",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function State:formatEyeColor(args, rowIndex)
local section = {}
local eyeValues = self:collectNumberedParams(args, "eye_color")
if #eyeValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P386',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(eyeValues, pbdValue)
end
end
if #eyeValues > 0 then
local displayValue = self:formatFeatureList(eyeValues, 'eye_color')
if displayValue then
section[#section + 1] = self:formatField("Eye color:",
displayValue,
"eye_color",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function State:formatBodyType(args, rowIndex)
local section = {}
local bodyValues = self:collectNumberedParams(args, "body_type")
if #bodyValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P399',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(bodyValues, pbdValue)
end
end
if #bodyValues > 0 then
local displayValue = self:formatFeatureList(bodyValues, 'body_type')
if displayValue then
section[#section + 1] = self:formatField("Body type:",
displayValue,
"body_type",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function State:formatSkin(args, rowIndex)
local section = {}
local skinValues = self:collectNumberedParams(args, "skincomplexion")
if #skinValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P421',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(skinValues, pbdValue)
end
end
if #skinValues > 0 then
local displayValue = self:formatFeatureList(skinValues, 'skin')
if displayValue then
section[#section + 1] = self:formatField("Skin:",
displayValue,
"skin",
rowIndex)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function State:formatAssType(args, rowIndex)
local section = {}
local assTypeValues = self:collectNumberedParams(args, "ass_type")
if #assTypeValues == 0 and args.qid then
local pbdValue = PBD._property{
[1] = 'P585',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
if not isEmpty(pbdValue) then
table.insert(assTypeValues, pbdValue)
end
end
if #assTypeValues > 0 then
local uniqueCategories = {}
local displayValues = {}
local hasMainType = false
local function isMainType(category)
return category == "Small Ass" or category == "Medium Ass" or category == "Big Ass"
end
for _, assType in ipairs(assTypeValues) do
local types = self:splitByComma(assType)
for _, t in ipairs(types) do
t = mw.text.trim(t):lower()
local mapping = CategoryMapping.MAPPINGS.ass_type[t]
if mapping then
if isMainType(mapping.category) then
if not hasMainType then
hasMainType = true
uniqueCategories[mapping.category] = true
end
else
uniqueCategories[mapping.category] = true
end
end
end
table.sort(foundMappings, function(a, b)
for category, _ in pairs(uniqueCategories) do
ifreturn #displayValuesa.priority >< 0 thenb.priority
end)
for i, mapping in ipairs(foundMappings) do
if i > 1 then
table.insert(displayValues, ", ")
end
local result = string.format("[[:Category:%s|%s]]", category, category)
if mw.title.getCurrentTitle().namespace == 0 thenmapping.category,
result = result mapping.. string.format("[[Category:%s]]", category)display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
end
else
if #displayValues > 0 then
for _, value in ipairs(values) do
section[#section + 1] = self:formatField("Ass type:",
if value table.concat(displayValues),then
"ass_type",local features = self:splitByComma(value)
rowIndexfor _, feature in ipairs(features) do
rowIndex = rowIndex + 1 feature = mw.text.trim(feature):lower()
end
for _, mapping in ipairs(CategoryMapping.MAPPINGS[featureType]) do
end
local found = false
for _, alias in ipairs(mapping.aliases) do
return section, rowIndex
if feature == alias:lower() then
end
found = true
if not addedCategories[mapping.category] then
function State:formatForeskin(args, rowIndex)
if #displayValues > 0 then
local section = {}
table.insert(displayValues, ", ")
end
local value = args.foreskin
if isEmpty(value) and args.qid then
local result = string.format("[[:Category:%s|%s]]",
value = PBD._property{
[1] = 'P398' mapping.category,
raw = true, mapping.display
multilanguage = true, )
['eid'] = args.qid
if isMainNamespace then
}
result = result .. string.format("[[Category:%s]]",
end
mapping.category
)
if not isEmpty(value) then
end
local displayValue = self:formatFeatureList({value}, 'foreskin')
if displayValue then
table.insert(displayValues, result)
section[#section + 1] = self:formatField("Foreskin:",
displayValue, addedCategories[mapping.category] = true
"foreskin", end
rowIndex) break
rowIndex = rowIndex + 1 end
end
if found then break end
end
end
return section, rowIndex
end
function State:formatChestHair(args, rowIndex)
local section = {}
local value = args.chest_hair
if not value and args.qid then
value = PBD._property{
[1] = 'P589',
raw = true,
multilanguage = true,
['eid'] = args.qid
}
end
if not isEmpty(value) then
value = mw.ustring.lower(value)
local mappings = CategoryMapping.MAPPINGS.chest_hair
local match = nil
for _, mapping in ipairs(mappings) do
for _, alias in ipairs(mapping.aliases) do
if mw.ustring.lower(alias) == value then
match = mapping
break
end
end
if match then break end
end
if match then
local displayValue = '[[:Category:' .. match.category .. '|' .. match.display .. ']] <small>([[:Category:Chest hair|Legend]])</small>'
if mw.title.getCurrentTitle().namespace == 0 then
displayValue = displayValue .. '[[Category:' .. match.category .. ']]'
end
section[#section + 1] = self:formatField(
"Chest hair:",
displayValue,
"chest_hair",
rowIndex
)
rowIndex = rowIndex + 1
end
end
return section, rowIndex
end
function State:formatBodySection(args, rowIndex)
local section = {}
if #displayValues > 0 then
section[#section + 1] = string.format('|-\n! colspan="2" %s | \'\'\'Body\'\'\'', STYLES.SECTION_HEADER)
return table.concat(displayValues)
section[#section + 1] = '<tr><td colspan="2" style="text-align:center;">'
section[#section + 1] = '<div style="width: 100%; border: 1px white; background:#657D91; padding: 1px 0; display: grid; grid-template-columns: auto auto auto; color: white; text-align: center;">'
section[#section + 1] = '<div>[[File:Height attribute symbol.png|40px|link=Height]]</div>'
section[#section + 1] = '<div>[[File:Weight attribute symbol.png|40px|link=Weight]]</div>'
section[#section + 1] = '<div>[[File:Penis size attribute symbol.png|40px|link=Penis size]]</div>'
local frame = mw.getCurrentFrame()
local height = getHeight(frame, args)
local weight = getWeight(frame, args)
local penisSize = getPenisSize(frame, args)
section[#section + 1] = string.format(
'<div>\'\'\'%s\'\'\'</div><div>\'\'\'%s\'\'\'</div><div>\'\'\'%s\'\'\'</div></div></td></tr>',
height, weight, penisSize
)
local hairSection, newRowIndex = self:formatHair(args, rowIndex)
for _, line in ipairs(hairSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local eyeSection, newRowIndex = self:formatEyeColor(args, rowIndex)
for _, line in ipairs(eyeSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local bodySection, newRowIndex = self:formatBodyType(args, rowIndex)
for _, line in ipairs(bodySection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local skinSection, newRowIndex = self:formatSkin(args, rowIndex)
for _, line in ipairs(skinSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local assTypeSection, newRowIndex = self:formatAssType(args, rowIndex)
for _, line in ipairs(assTypeSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local foreskinSection, newRowIndex = self:formatForeskin(args, rowIndex)
for _, line in ipairs(foreskinSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
return nil
local chestHairSection, newRowIndex = self:formatChestHair(args, rowIndex)
for _, line in ipairs(chestHairSection) do
section[#section + 1] = line
end
rowIndex = newRowIndex
local tattooValue = args.tattoo
if not isEmpty(tattooValue) then
if isPositive(tattooValue) then
local displayValue = '[[:Category:Performers with Tattoos|Yes]]'
if mw.title.getCurrentTitle().namespace == 0 then
displayValue = displayValue .. '[[Category:Performers with Tattoos]]'
end
local tattooLine = string.format('|-\n! style="%s %s" | \'\'\'%s\'\'\'\n| style="%s text-align:left;" | %s',
self:getRowStyle(rowIndex),
STYLES.LABEL,
'Tattoo:',
self:getRowStyle(rowIndex),
displayValue)
section[#section + 1] = tattooLine
rowIndex = rowIndex + 1
end
end
return table.concat(section, '\n'), rowIndex
end
local state = State:new()
local personalSection, rowIndex = state:BioboxPersonal.formatPersonalSection(state, args, title)
local bodySection = state:BioboxBody.formatBodySection(state, args, rowIndex)
local personalPagesSection, ppRowIndex = BioboxPersonalPages.formatPersonalPagesSection(state, args, rowIndex)
local databasesSection, dbRowIndex = BioboxDatabases.formatDatabasesSection(state, args, ppRowIndex)
local sharingSection, shRowIndex = BioboxSharing.formatSharingSection(state, args, dbRowIndex)
local result = personalSection .. '\n' .. bodySection
if #personalPagesSection > 0 then
result = result .. '\n' .. table.concat(personalPagesSection, '\n')
end
if #databasesSection > 0 then
result = result .. '\n' .. table.concat(databasesSection, '\n')
end
if #sharingSection > 0 then
result = result .. '\n' .. table.concat(sharingSection, '\n')
end
if args.qid then
result = result .. '\n|}'
local categories = state:BioboxPersonal.getPBDCategories(args)
if #categories > 0 then
local categoryStrings = {}
|