Documentation for this module may be created at Module:ClassDefinitionData/doc
local CspFunctions = require('Module:CspFunctions')
local p = {}
--[[
function p.get(page,contentPageData)
arguments:
- page = (string) class definition page, e.g. "Wiki:Class definition/Application page"
- contentPageData = (optional: table) slotdata of a content page, with the same class that is defined by the class definition page, e.g. "Template:Csp sidebar tabs"
if this is used, then values from contentPageData will be added to CspParameterDefinitions when possible.
example
p.get("Wiki:Class definition/Application page")
defines data table with subtables:
data["ws-base-props"] slotdata
data["ws-class-props"] slotdata
data["ws-data"] slotdata
["CspParameterDefinitions"] default and additional values are added to the values from the ws-data slot
["name"]
["propertyName"]
["required"]
["multiple"]
["formfieldTemplate"]
["allowedValues"]
["slot"]
["slotTemplate"]
["displayTemplate"]
["value"]
data["var"] variables defined through this module
["basePropsTemplate"] full pagename of base properties template, defaults to "Template:Base properties"
["basePropsTemplateName"] pagename of base properties template, for example "Base properties"
["classPropsTemplate"] full pagename of class properties template, defaults to "Template:Csp class properties", for example "Template:Person properties"
["classPropsTemplateName"] pagename of class properties template, for example "Person properties"
["footerTemplate"] full pagename of footer template, for example "Template:Csp custom footer/Person". Defaults to "".
["sidebarTemplateName"] pagename of footer template, for example Csp custom footer/Person". Defaults to "".
["sidebarTemplate"] full pagename of sidebar template, defaults to "Template:Csp default sidebar"
["sidebarTemplateName"] pagename of sidebar template, for example "Csp default sidebar" or "Csp custom sidebar/Person"
["subheaderTemplate"] full pagename of subheader template, defaults to "Template:Csp default subheader"
["subheaderTemplateName"] pagename of subheader template, for example "Csp default subheader" or "Csp custom subheader/Person"
["pagetitleFormat"] "title" if set to "title", else default to "next_available"
["hasParameterDefinitions"] "yes" or "no" depending on whether data["ws-data"]["CspParameterDefinitions"] exists
["hasFooter"] "true" or "false", true if "footer" is found in the "Layout areas" parameter and footer template is not empty.
["hasSidebar"] "true" or "false", true if "sidebar" is found in the "Layout areas" parameter
["hasSubheader"] "true" or "false", true if "sub-header" is found in the "Layout areas" parameter
["customParameterDefinitionFields"] contains subtable with custom fields as keys
debug console tests:
p.get("Wiki:Class definition/Class definition")
--]]
function p.get(page,contentPageData)
-- get page from frame args or default to current page
if page == nil or page == '' then
page = mw.title.getCurrentTitle().fullText
end
-- get slot data for each slot and add to data table
local data = {}
for slot in string.gmatch("ws-base-props,ws-class-props,ws-data", '([^,]+)') do
local slotData = CspFunctions.getSlotData(page,slot)
if slotData == nil then slotData = "" end
data[slot] = slotData
end
-- return if class is not "Class definition"
if data["ws-base-props"]["Base properties"] == nil then return end
if data["ws-base-props"]["Base properties"][1]["Class"]["_text"] ~= "Class definition" then return end
local variables = {}
-- function to get pagename from full pagename (removes namespace by removing everything up to and including the first ":")
local function pagename(fullpagename)
return fullpagename:gsub("[^:]*:","",1)
end
local basePropsTemplate, classPropsTemplate, footerTemplate, sidebarTemplate, subheaderTemplate
-- get basePropsTemplate or set default
if data["ws-class-props"]["Csp class properties"][1]["Base properties template"] then
basePropsTemplate = data["ws-class-props"]["Csp class properties"][1]["Base properties template"]["_text"]
end
if basePropsTemplate == nil or basePropsTemplate == "" then basePropsTemplate = "Template:Base properties" end
-- get classPropsTemplate or set default
if data["ws-class-props"]["Csp class properties"][1]["Page properties template"] then
classPropsTemplate = data["ws-class-props"]["Csp class properties"][1]["Page properties template"]["_text"]
end
if classPropsTemplate == nil or classPropsTemplate == "" then
classPropsTemplate = "Template:Csp class properties"
end
-- get footerTemplate or set default
if data["ws-class-props"]["Csp class properties"][1]["Footer template"] then
footerTemplate = data["ws-class-props"]["Csp class properties"][1]["Footer template"]["_text"]
end
if footerTemplate == nil or footerTemplate == "" then
footerTemplate = ""
end
-- get sidebarTemplate or set default
if data["ws-class-props"]["Csp class properties"][1]["Sidebar template"] then
sidebarTemplate = data["ws-class-props"]["Csp class properties"][1]["Sidebar template"]["_text"]
end
if sidebarTemplate == nil or sidebarTemplate == "" then
sidebarTemplate = "Template:Csp default sidebar"
end
-- get subheaderTemplate or set default
if data["ws-class-props"]["Csp class properties"][1]["Sub header template"] then
subheaderTemplate = data["ws-class-props"]["Csp class properties"][1]["Sub header template"]["_text"]
end
if subheaderTemplate == nil or subheaderTemplate == "" then
subheaderTemplate = "Template:Csp default subheader"
end
local pagetitleFormat = data["ws-class-props"]["Csp class properties"][1]["Pagetitle format"]["_text"]
if pagetitleFormat ~= "title" then pagetitleFormat = "next_available" end
local layoutAreas = ""
local hasFooter = "false"
local hasSidebar = "false"
local hasSubheader = "false"
if data["ws-class-props"]["Csp class properties"][1]["Layout areas"] then
layoutAreas = data["ws-class-props"]["Csp class properties"][1]["Layout areas"]["_text"]
for component in string.gmatch(layoutAreas, '([^ \'"]+)') do
if component == "sidebar" then
hasSidebar = "true"
elseif component == "sub-header" then
hasSubheader = "true"
elseif component == "footer" then
hasFooter = "true"
end
end
end
variables["basePropsTemplate"] = basePropsTemplate
variables["basePropsTemplateName"] = pagename(basePropsTemplate)
variables["classPropsTemplate"] = classPropsTemplate
variables["classPropsTemplateName"] = pagename(classPropsTemplate)
variables["footerTemplate"] = footerTemplate
variables["footerTemplateName"] = pagename(footerTemplate)
variables["sidebarTemplate"] = sidebarTemplate
variables["sidebarTemplateName"] = pagename(sidebarTemplate)
variables["subheaderTemplate"] = subheaderTemplate
variables["subheaderTemplateName"] = pagename(subheaderTemplate)
variables["pagetitleFormat"] = pagetitleFormat
variables["hasFooter"] = hasFooter
variables["hasSidebar"] = hasSidebar
variables["hasSubheader"] = hasSubheader
-- loop through ws-data CspParameterDefinitions to add default values
-- also check for custom fields
variables["hasParameterDefinitions"] = "no"
local customFields = {}
if data["ws-data"]["CspParameterDefinitions"] ~= nil then
variables["hasParameterDefinitions"] = "yes"
for i, v in pairs (data["ws-data"]["CspParameterDefinitions"]) do
-- loop through fields to check for custom ones
local defaultFields = {["name"]=true,["propertyName"]=true,["allowedVelues"]=true}
local defaultFields = {["name"] = true,
["propertyName"] = true,
["required"] = true,
["multiple"] = true,
["formfieldTemplate"] = true,
["allowedValues"] = true,
["slot"] = true,
["showOnCreate"] = true,
["displayTemplate"] = true,
["value"] = true
}
for field,value in pairs(v) do
if defaultFields[field] ~= true then
customFields[field] = true
end
end
local name = data["ws-data"]["CspParameterDefinitions"][i]["name"]
local propertyName = data["ws-data"]["CspParameterDefinitions"][i]["propertyName"]
local slot = data["ws-data"]["CspParameterDefinitions"][i]["slot"]
local value = data["ws-data"]["CspParameterDefinitions"][i]["value"]
-- set default values when necessary
if propertyName == nil or propertyName == "" then
propertyName = name
data["ws-data"]["CspParameterDefinitions"][i]["propertyName"] = propertyName
end
if slot == nil or slot == "" then
slot = "ws-class-props"
data["ws-data"]["CspParameterDefinitions"][i]["slot"] = slot
end
-- add slotTemplate, so this can be used more easily in for example _edit in a form
local slotTemplate = ""
if slot == "ws-base-props" then
slotTemplate = "Base properties"
else
slotTemplate = "Csp class properties"
end
data["ws-data"]["CspParameterDefinitions"][i]["slotTemplate"] = slotTemplate
-- add value from contentPageData if possible
if type(contentPageData) == "table" then
if contentPageData[slot] and contentPageData[slot][slotTemplate] and contentPageData[slot][slotTemplate][1][name] then
local value = contentPageData[slot][slotTemplate][1][name]["_text"]
data["ws-data"]["CspParameterDefinitions"][i]["value"] = value
end
end
end
end
-- add extra subtable for "variables" derived from slotdata
variables["customParameterDefinitionFields"] = customFields
data["var"] = variables
--mw.logObject(data)
return data
end
--[[
function p.afExport(frame)
frame args:
page (text) defaults to current page
{{#invoke:ClassDefinitionData|afExport}}
{{#invoke:ClassDefinitionData|afExport|page=Wiki:Class definition/Application page}}
debug console tests:
=p.afExport(mw.getCurrentFrame():newChild{title="whatever",args={["page"]="Wiki:Class definition/Application page"}})
=p.afExport(mw.getCurrentFrame():newChild{title="whatever",args={}})
--]]
function p.afExport(frame)
-- get slot data for each slot and add to data table
local data = {}
data[1] = p.get(frame.args["page"])
--mw.logObject(data)
return mw.af.export(data)
end
--[[
function p.set(frame)
{{#invoke:ClassDefinitionData|set}}
This function sets properties based on Class definition data, or alternatively parsed a properties template, when this function is called from a different template than the one specified in the class definition data. This function is used by the default "Csp class properties" template, but can also be used in custom property templates, which can be useful when you want default properties as well as add additional custom properties.
debug console tests:
=p.set(mw.getCurrentFrame():newChild{title="whatever",args={["page"]="Persoon_test/Tester"}})
=p.set(mw.getCurrentFrame():newChild{title="Template:Csp class properties",args={["TextAreaInput"]="123",["TokenMultipleInput"]="Alpha,Charlie"}}:newChild{title="Module:ClassDefinitionData",args={["page"]="Persoon_test/Tester"}})
--]]
function p.set(frame)
-- get page from frame args or default to current page
local page = frame.args["page"]
if page == nil or page == '' then
page = mw.title.getCurrentTitle().fullText
end
-- get pageData (i.e. slotdata from page)
local pageData = {}
pageData["ws-base-props"] = mw.slots.slotData("ws-base-props",page)
pageData["ws-class-props"] = mw.slots.slotData("ws-class-props",page)
-- get class from pageData
local class = ""
if pageData and pageData["ws-base-props"] and pageData["ws-base-props"]["Base properties"] and pageData["ws-base-props"]["Base properties"][1]["Class"] then
class = pageData["ws-base-props"]["Base properties"][1]["Class"]["_text"]
else
return
end
-- get classData (i.e. slotdata and Class definition specific data from class definition page)
local classDefinitionPage = CspFunctions.ClassToClassDefinitionPage{["args"]={class}}
local classData = p.get(classDefinitionPage)
if classData == nil or classData == {}
then return "no classData"
end
-- check for custom properties template (i.e. a template that is different than the parent template this function is called from)
local parentTitle = frame:getParent():getTitle()
local classPropsTemplate = classData["var"]["classPropsTemplate"]
if parentTitle ~= classPropsTemplate and classPropsTemplate ~= "Template:Csp class properties" then
-- return if classPropsTemplate does not have an appropriate value
if classPropsTemplate == nil or classPropsTemplate == "" then return end
-- parse classPropsTemplate, pass all frame args as parameters, as well as afExport of pageData
-- first construct a new table with parent args, this is done by a loop rather than copying the parent args,
-- as copying made it impossible to add new table elements (like $pageData)
local propertyTemplateArgs = {}
for key,value in pairs(frame:getParent().args) do propertyTemplateArgs[key] = value end
propertyTemplateArgs["$pageData"] = mw.af.export(pageData)
local result = frame:expandTemplate {
title = classPropsTemplate,
args = propertyTemplateArgs
}
return result
else
-- else set default properties based on a loop through CspParameterDefinitions in classData
if classData["ws-data"]["CspParameterDefinitions"] == nil then return end
local properties = {}
-- properties table will be filled through a loop with the following structure:
-- single value properties: properties["propertyName"] = "propertyValue"
-- multiple value properties: properties["propertyName"] = {"propertyValue1","propertyValue2","propertyValue3"}
-- only parameters for the ws-class-props slot are added to properties
for i, parameter in pairs (classData["ws-data"]["CspParameterDefinitions"]) do
-- check if the value exists in pageData and if slot equals ws-class-props and propertyName does not equal "(none)"
if parameter["slot"] == "ws-class-props" and pageData[parameter["slot"]] and pageData[parameter["slot"]][parameter["slotTemplate"]]
and parameter["propertyName"] ~= "(none)" and pageData[parameter["slot"]][parameter["slotTemplate"]][1][parameter["name"]] then
-- proceed to add the value to the properties table
local propertyValue = pageData[parameter["slot"]][parameter["slotTemplate"]][1][parameter["name"]]["_text"]
if parameter["multiple"] == "true" then
-- split string into a table with separate values, split by commas (one or multiple) and remove potential spaces around the commas
propertyValue = mw.text.split(propertyValue,"%s*,+%s*")
end
-- add property name and value to the properties table
properties[parameter["propertyName"]] = propertyValue
end
end
-- set properties
mw.logObject(properties)
local result = mw.smw.set(properties)
-- check for errors
if result ~= true then
mw.smw.set({["CspError"] = result.error})
return "ERROR from Module:ClassDefinitionData, p.set, mw.smw.set = " .. result.error
end
end
end
return p