Module:Biobox
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Biobox/doc
local p = {}
local PBDIB = require('Module:PornBaseDataIB')
local CategoryMapping = require('Module:BioboxCategoryMapping')
local BioboxPersonal = require('Module:BioboxPersonal')
local BioboxBody = require('Module:BioboxBody')
local BioboxPerformances = require('Module:BioboxPerformances')
local BioboxPersonalPages = require('Module:BioboxPersonalPages')
local BioboxDatabases = require('Module:BioboxDatabases')
local BioboxSharing = require('Module:BioboxSharing')
local BioboxVODDVD = require('Module:BioboxVODDVD')
local Utils = require('Module:BioboxUtils')
local ALIAS_TO_PRIMARY = {}
do
for primary, aliases in pairs(CategoryMapping.PARAM_ALIASES) do
for _, alias in ipairs(aliases) do
ALIAS_TO_PRIMARY[alias] = primary
end
ALIAS_TO_PRIMARY[primary] = primary
end
end
local STYLES = {
INFOBOX = 'class="infoboxnew" cellspacing="1" cellpadding="1" style="text-align:center; font-size:88%; line-height:1.5em; white-space:normal;"',
HEADER = 'style="color:white; text-align:center; border: 1px solid white; background:#657D91; font-size:112%;"',
LABEL = 'width:40%; padding-left:0.1em; overflow-wrap: break-word; font-weight:normal; text-align:left;',
SECTION_HEADER = 'style="color:white; text-align:center; border: 1px solid white; background:#657D91; font-size:100%;"',
ODD_ROW = 'background-color:#F7F7F7;',
EVEN_ROW = 'background-color:white;'
}
local function isEmpty(value)
return Utils.isEmpty(value)
end
local function isPositive(value)
return Utils.isPositive(value)
end
local POSITIVE_ONLY_FIELDS = {
}
local function normalizeKeys(args)
local normalized = {}
local seenParams = {}
local processedAliases = {}
local firstOccurrence = {}
for key, value in pairs(args) do
local normalizedKey = tostring(key):gsub(" ", "_"):lower()
local primaryKey = ALIAS_TO_PRIMARY[normalizedKey] or normalizedKey
if not firstOccurrence[primaryKey] then
firstOccurrence[primaryKey] = #seenParams + 1
end
table.insert(seenParams, {
key = key,
value = value,
normalizedKey = normalizedKey,
primaryKey = primaryKey,
position = firstOccurrence[primaryKey]
})
end
table.sort(seenParams, function(a, b)
return a.position < b.position
end)
for _, param in ipairs(seenParams) do
local primaryKey = param.primaryKey
if not processedAliases[primaryKey] then
if not isEmpty(param.value) then
normalized[primaryKey] = param.value
processedAliases[primaryKey] = true
elseif not normalized[primaryKey] then
normalized[primaryKey] = param.value
end
end
end
return normalized
end
local function isNumeric(value)
if type(value) == "number" then return true end
if type(value) ~= "string" then return false end
return tonumber(value) ~= nil
end
local function shouldDisplayField(fieldName, value)
if not isEmpty(value) then
if POSITIVE_ONLY_FIELDS[fieldName] then
return isPositive(value)
end
return true
end
return false
end
local function getPBDIBValue(propertyId, args, options)
return PBDIB._getValue({
[1] = propertyId,
qid = args.qid,
format = options and options.format,
fpbd = "ALL"
})
end
local function extractNumber(str)
if type(str) == 'number' then
return str
end
if type(str) ~= 'string' or str == '' then
return nil
end
local num = tonumber(str)
if num then return num end
num = str:match("^%s*(%d+%.?%d*)[%s%a]*$")
if num then return tonumber(num) end
num = str:match("^%s*(%d+%.?%d*)%a*$")
if num then return tonumber(num) end
num = str:match("^%s*(%d+,%d+)%s*$")
if num then return tonumber(num:gsub(",", ".")) end
return nil
end
local State = {}
function State:new()
local state = {}
setmetatable(state, self)
self.__index = self
state.STYLES = STYLES
return state
end
function State:getRowStyle(index)
return index % 2 == 1 and STYLES.ODD_ROW or STYLES.EVEN_ROW
end
function State:splitByComma(str)
return Utils.splitByComma(str)
end
function State:formatCategoryLink(value, prefix, displayText)
if isEmpty(value) then return nil end
local normalized = mw.text.trim(value):gsub("^%l", string.upper)
displayText = displayText or normalized
local result = string.format("[[:Category:%s%s|%s]]",
prefix,
normalized,
displayText
)
if mw.title.getCurrentTitle().namespace == 0 then
result = result .. string.format("[[Category:%s%s]]",
prefix,
normalized
)
end
return result
end
function State:collectNumberedParams(args, baseParam)
local values = {}
local numbered = {}
if not isEmpty(args[baseParam]) then
table.insert(values, {index = 0, value = args[baseParam]})
end
for param, value in pairs(args) do
local index = param:match("^" .. baseParam .. "(%d+)$")
if index and not isEmpty(value) then
index = tonumber(index)
if index and index > 0 and index < 100 then
table.insert(values, {index = index, value = value})
end
end
end
table.sort(values, function(a, b) return a.index < b.index end)
local result = {}
for _, item in ipairs(values) do
table.insert(result, item.value)
end
return result
end
function State:formatField(label, value, fieldName, index)
if isEmpty(value) then
return ''
end
if POSITIVE_ONLY_FIELDS[fieldName] and not isPositive(value) then
return ''
end
local rowStyle = self:getRowStyle(index)
return string.format('|-\n! style="%s %s" | \'\'\'%s\'\'\'\n| style="%s text-align:left;" | %s',
rowStyle,
STYLES.LABEL,
label,
rowStyle,
value)
end
function State:formatFeatureList(values, featureType)
if not values or #values == 0 then return nil end
local displayValues = {}
local addedCategories = {}
local isMainNamespace = mw.title.getCurrentTitle().namespace == 0
if featureType == 'foreskin' then
for _, value in ipairs(values) do
if value then
local feature = mw.text.trim(value):lower()
local mapping = CategoryMapping.MAPPINGS[featureType][feature]
if mapping then
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
return result
end
end
end
return nil
end
if featureType == 'ass_type' then
local foundMappings = {}
local hasMainType = false
for _, value in ipairs(values) do
if value then
local features = self:splitByComma(value)
for _, feature in ipairs(features) do
feature = mw.text.trim(feature):lower()
for _, mapping in ipairs(CategoryMapping.MAPPINGS[featureType]) do
for _, alias in ipairs(mapping.aliases) do
if feature == alias:lower() then
local isMainSize = mapping.priority >= 1 and mapping.priority <= 3
if (not isMainSize or not hasMainType) and not addedCategories[mapping.category] then
table.insert(foundMappings, mapping)
addedCategories[mapping.category] = true
if isMainSize then
hasMainType = true
end
end
end
end
end
end
end
end
table.sort(foundMappings, function(a, b)
return a.priority < b.priority
end)
for i, mapping in ipairs(foundMappings) do
if i > 1 then
table.insert(displayValues, ", ")
end
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
end
else
for _, value in ipairs(values) do
if value then
local features = self:splitByComma(value)
for _, feature in ipairs(features) do
feature = mw.text.trim(feature):lower()
for _, mapping in ipairs(CategoryMapping.MAPPINGS[featureType]) do
local found = false
for _, alias in ipairs(mapping.aliases) do
if feature == alias:lower() then
found = true
if not addedCategories[mapping.category] then
if #displayValues > 0 then
table.insert(displayValues, ", ")
end
local result = string.format("[[:Category:%s|%s]]",
mapping.category,
mapping.display
)
if isMainNamespace then
result = result .. string.format("[[Category:%s]]",
mapping.category
)
end
table.insert(displayValues, result)
addedCategories[mapping.category] = true
end
break
end
end
if found then break end
end
end
end
end
end
if #displayValues > 0 then
return table.concat(displayValues)
end
return nil
end
local function loadTemplateStyles()
local frame = mw.getCurrentFrame()
local base_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = 'Module:Biobox/styles.css' }
}
return base_templatestyles
end
function p.main(frame)
local parentFrame = frame:getParent()
local args = frame.args
if not next(args) then
args = parentFrame.args
end
args = normalizeKeys(args)
if not args.qid or args.qid == "" then
args.qid = mw.wikibase.getEntityIdForCurrentPage()
end
local title = mw.title.getCurrentTitle().text
local state = State:new()
local personalSection, rowIndex = BioboxPersonal.formatPersonalSection(state, args, title)
local bodySection, bodyRowIndex = BioboxBody.formatBodySection(state, args, rowIndex)
local performancesSection, perfRowIndex = BioboxPerformances.formatPerformancesSection(state, args, bodyRowIndex)
local personalPagesSection, ppRowIndex = BioboxPersonalPages.formatPersonalPagesSection(state, args, perfRowIndex)
local databasesSection, dbRowIndex = BioboxDatabases.formatDatabasesSection(state, args, ppRowIndex)
local sharingSection, shRowIndex = BioboxSharing.formatSharingSection(state, args, dbRowIndex)
local vodDvdSection, vodRowIndex = BioboxVODDVD.formatVODDVDSection(state, args, shRowIndex)
local result = personalSection .. '\n' .. bodySection .. '\n' .. performancesSection
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 #vodDvdSection > 0 then
result = result .. '\n' .. table.concat(vodDvdSection, '\n')
end
if args.qid then
local pbcLink = mw.wikibase.getSitelink(args.qid)
if pbcLink then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Pbd.svg | 45px | alt=' .. args.qid .. ' | link=pbd:' .. args.qid .. ']] [[:pbd:' .. args.qid .. '|' .. pbcLink .. ']] ([[:pbd:' .. args.qid .. '|' .. args.qid .. ']])'
end
local newFrame = {
args = {
qid = args.qid,
wiki = "pbcimagerepo"
}
}
local imageRepoLink = PBDIB.getSiteLink(newFrame)
if imageRepoLink and imageRepoLink ~= '' then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Image-icon.svg | 18px | link=:' .. imageRepoLink .. ']] [[:' .. imageRepoLink .. '| PBC Image Repository]]'
end
newFrame.args.wiki = "pbcvideorepo"
local videoRepoLink = PBDIB.getSiteLink(newFrame)
if videoRepoLink and videoRepoLink ~= '' then
result = result .. '\n|-class="stop-section-collapse"\n! colspan="2" style="background:#F0E68C;text-align:center;" | [[File:Video-icon.svg | 18px | link=:' .. videoRepoLink .. ']] [[:' .. videoRepoLink .. '| PBC Video Repository]]'
end
end
result = result .. '\n|}'
local categories = BioboxPersonal.getPBDCategories(args)
if #categories > 0 then
local categoryStrings = {}
for _, category in ipairs(categories) do
table.insert(categoryStrings, '[[Category:' .. category .. ']]')
end
result = result .. '\n' .. table.concat(categoryStrings, '\n')
end
return loadTemplateStyles() .. '\n' .. result
end
return p