imported>Oetterer K (Schützte „Modul:Classgenerator/class“: Automatic protection of selected project pages ([Bearbeiten=Nur Administratoren erlauben] (unbeschränkt) [Verschieben=Nur Administratoren erlauben] (unbeschränkt))) |
|
(kein Unterschied)
|
Version vom 7. Oktober 2022, 16:56 Uhr
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This is a Class Module. It implements a class in Lua using Module:Middleclass and the template class Module:Foundationclass. This class provides methods for PURPOSE.
Usage[Quelltext bearbeiten]
local name = args[1] or args.name or mw.title.getCurrentTitle().rootText
local Class = require('Module:Name/class')
local me = Class:new(name)
me:initDataFromArgs(args)
me:storeData()
me:addInfobox()
me:addPageBody()
return me:render()
Methods[Quelltext bearbeiten]
Constructor[Quelltext bearbeiten]
new(uid)[Quelltext bearbeiten]
Creates a new Object for the class.
- uid
- variable, optional
- used to identify the object
- return
- object, of the class
public methods[Quelltext bearbeiten]
addInfobox()[Quelltext bearbeiten]
If no errors and data is present, adds an infobox to the object's output.
- return
- boolean, whether adding was successful or not
addPageBody()[Quelltext bearbeiten]
Adds a page body (all content besides the infobox) to the object's output: Errors and Warnings, sample configuration, statistics, ... Of course, only if there is data.
- return
- boolean, whether adding was successful or not
myArgumentProcessing(coreData)[Quelltext bearbeiten]
Performs the individual argument processing in initDataFromArgs(args) right before inititializing it.
- coreData
- table, mandatory
- the core data of the object. the one to process individually before initialization
- return
- table, the new core data array to be used
myPlausibilityTest(args)[Quelltext bearbeiten]
Performs the individual plausibility tests in initDataFromArgs(args) before entering the initialization part. NOTE: The return value will be ignored. If this finds errors, it must add them to the list of errors via addError(errortext).
- args
- table, mandatory
- arguments passed to the template to be checked
- return
- boolean, whether the object is plausible or not.
myStashAdjustments(self, stash)[Quelltext bearbeiten]
Performs the adjusts the stash in storeData() right before storing it.
- stash
- table, mandatory
- the array of data to be saved (in the form fieldname: value)
- return
- boolean, the new stash
static methods[Quelltext bearbeiten]
ClassClassgenerator:mySfDynamicFieldAttribute(fieldname, attribute, value)[Quelltext bearbeiten]
For some semantic form fields there are attribute values, that are not static, thus can not be provided at forehand in the configuration file. This method does the trick to adapt them at runtime shortly before the field is rendered. Essentially: the method checks, if it has a special rule for the pair fieldname:attribute and if so, calculates the new value. if not, the old value is returned.
- fieldname
- string, mandatory
- the form field's name, needed to match current paring to an existing special treatment rule
- attribute
- string, mandatory
- the form field's attribute, needed to match current paring to an existing special treatment rule
- value
- variable, mandatory
- the value, that is already provided in the configuration file. this will be adapted by the method, if there is a special rule for the pair fieldname:attribute.
- return
- string, the value to be used forthwith (which can be the old one or a freshly calculated)
private methods[Quelltext bearbeiten]
_debug(self, level, text)[Quelltext bearbeiten]
Adds output to the internal debug log.
- self
- object, me
- level
- int; mandatory
- debug level for the message
- text
- string; mandatory
- debug message text
- return
- void
_namespaceName (self, namespaceId)[Quelltext bearbeiten]
Takes the id of a namespace and converts it to the human readable name. Normally returns mw.site.namespaces[id].canonicalName...
- self
- object, me
- namespaceId
- int; mandatory
- for which namespace id the name should be returned
- return
- string, name of namespace
_processAttribute(self, attr, indent, name)[Quelltext bearbeiten]
Takes an attribute and builds from that (and self:getCoreData()) one entry in the class's config file.
- self
- object, me
- attr
- string; mandatory
- for which attribute should the entry be build
- indent
- string; mandatory
- indentation of line
- name
- string; optional
- normally the parameter name will be constructed out of attr. if you have special needs as a name, you can supply them via this parameter. name takes precedence, if provided.
- return
- string, the entry that can directly be added to the config file/string
Properties[Quelltext bearbeiten]
static[Quelltext bearbeiten]
See also Static Properties
- ClassName.myConfiguration
- this is your configuration. It is devided in several section, each a
- table, holds configuration data found in Module:Name/config
- WARNING: This is a read only table and besides functions pairs() and ipairs() nothing else will work on it, especially not the functions of the table library!
- form, table, holds data used to create the form. here are some of them:
- formButtons, table, which buttons should be printed at the bottom
- fieldOrder, table, in which order the form fields should appear (note: only fields listed here will be added to the form)
- global, table, holds some global configuration data
- parameter, table, holds all data about all parameter used in the module (be they form only, data store only or normal). The table has the form paramname = { table of paramdata }. The tables for the parameter have data as follows:
- cardinality, string, mandatory, one of singe or list
- cargo_type, string, optional, if the parameter is to be stored in cargo, add the field type here (one of Page, Text, Integer, Float, Date, Datetime, Boolean (which should be provided as 1 or 0), Coordinates, Wikitext, File, String, URL, or Email)
- description, string, mandatory, a description of this parameter
- label, string, mandatory, the label used in the form and the template documentation
- severity, string, optional, if provided one of mandatory, suggested
- sf, table, optional, used to add more attributes to the semantic forms field. ref Module:SFfield/config for all possible attributes. Note that the table is of type attribute_name : value. Value can be of type string, integer, boolean, and (in case of 'show on select') a table. Please note, that the attribute name cannot contain a " " (space). Use the underscore instead.
- td_default, string, optional, if you want a default value to be indicated in the template data section on the documentation page, add it here
- td_type, string, optional, if the parameter should be present in the template documentation page, fill this field. all possible values are listed here
- values, table, optional, if you want the possible values to be restricted to a specific set, fill this table
- template, table, holds some data used only in the template
- className.publicStaticProperty
- type, explanation
- _privateStaticProperty
- type, explanation
private[Quelltext bearbeiten]
Note: all private properties are stored in table _private[self]. _private is a static array that is indexed by self, so the table _private[self] holds all properties for instance self.
- dbg
- object, my instance of Module:Debug/class for debugging purposes. only present afer first call of _debug(self, level, text)
Configuration Data[Quelltext bearbeiten]
This class holds its control data in Module:Classgenerator/config.
Inheritance[Quelltext bearbeiten]
Methods[Quelltext bearbeiten]
Note: You still reference those either by self:publicMethod() or Classgenerator:staticMethod() and Classgenerator.staticProperty respectively! MediaWiki:Classengine-content-documentation-methods
Static Properties[Quelltext bearbeiten]
MediaWiki:Classengine-content-documentation-properties
Dependecies[Quelltext bearbeiten]
Apart from the obvious (being all pages in Category:Class engine), we also need:
- {{((}}
- {{))}}
- Extension:Header Tabs
Nice to have:
Please check also Foundationclass's dependencies.
Interface messages[Quelltext bearbeiten]
To generate your project's meta categories, Classgenerator makes use of the following interface messages:
- MediaWiki:Classengine-content-project-form-category
- MediaWiki:Classengine-content-project-gardening-supercategory
- MediaWiki:Classengine-content-project-module-category
- MediaWiki:Classengine-content-project-property-category
- MediaWiki:Classengine-content-project-supercategory
- MediaWiki:Classengine-content-project-template-category
You may edit them freely for your convenience to suit your needs.
local FoundationClass = require('Module:Foundationclass')
local ClassDebug = require('Module:Debug/class')
-- ****************************************************************
-- * inheritance *
-- ****************************************************************
local Classgenerator = FoundationClass:subclass('Classgenerator')
-- setting class's configuration data
Classgenerator.static.myConfiguration = mw.loadData('Module:Classgenerator/config')
-- being in a static method, use self.myConfiguration
-- being in a private method, that knows self or in a public method, use self.class.myConfiguration
-- ****************************************************************
-- * properties *
-- ****************************************************************
-- **************** initialization of table for private properties
local _private = setmetatable({}, {__mode = 'k'}) -- weak table storing all private attributes
-- **************** declaration of public static properties
-- Classgenerator.static.myPropertyModule = require('Module:extern')
-- Classgenerator.static.staticProperty = 'value'
-- remember the static classes provided by Foundationclass:
-- Classgenerator.globalConfig
-- Classgenerator.myCargoUtil
-- Classgenerator.myTableTools
-- **************** declaration of (global) private properties
-- for properties you should rather use constructor and _private[self]. this only, if you need a private class property
-- you should, however predeclare private methods here
local _debug -- private method declared later
local _privateMethodAhead -- declaration ahead, so this private method can be used in the constructor and in other private methods
-- ***************************************************************
-- * methods *
-- ***************************************************************
-- **************** declaration of static methods
function Classgenerator:initialize(uid)
local _CFG = self.class.myConfiguration
FoundationClass.initialize(self, uid)
local page = mw.title.getCurrentTitle().text
if uid and mw.ustring.match(uid, '^' .. _CFG.global.namespace .. ':.+$') then
page = mw.ustring.match(uid, '^' .. _CFG.global.namespace .. ':(.+)$')
end
_private[self] = {
dbg = ClassDebug:new(tostring(self.class) .. ': id ' .. uid),
pagename = page
}
_debug(self, 1, ' Classgenerator: done initializing object "' .. uid ..'", from ' .. tostring(self))
end
-- use use self.myConfiguration to access your configuration in a static method
function Classgenerator.static:aStaticMethod(var)
_debug(self, 1, 'entering Classgenerator.static:aStaticMethod() to do something, from ' .. tostring(self))
end
function Classgenerator.static:mySfDynamicFieldAttribute(fieldname, attribute, value)
_debug(self, 1, 'entering Classgenerator.static:mySfDynamicFieldAttribute(fieldname, attribute, value), from ' .. tostring(self))
_debug(self, 2, ' with parameters "' .. fieldname .. '", "' .. attribute .. '" and a ' .. type(value) .. ' value')
-- function that can process any attribute/value pair just before rendering the semantic forms field
-- usually done, to generate a dynamic 'default' value
-- keep in mind: you can completely disable a form field, if you return true on attribute "disable". note however, that this causes the field to not show at all, no data will be transported/saved
local pagename = mw.title.getCurrentTitle().text
local val = value
if fieldname == 'template_name' and attribute == 'default' then
val = mw.ustring.lower(pagename)
end
if fieldname == 'global_entityTitle' and attribute == 'default' then
val = mw.ustring.gsub(pagename, '[ /]', '')
end
if fieldname == 'global_cargoTable' and attribute == 'default' then
val = mw.ustring.gsub(pagename, '[ /]', '')
end
if Classgenerator.globalConfig.dataStore ~= 'cargo' and Classgenerator.globalConfig.dataStore ~= 'both' then
if fieldname == 'global_cargoTable' and attribute == 'disable' then
val = true
end
if fieldname == 'global_cargoUidFieldname' and attribute == 'disable' then
val = true
end
end
if Classgenerator.globalConfig.dataStore ~= 'smw' and Classgenerator.globalConfig.dataStore ~= 'both' then
if fieldname == 'global_smwIsSubobject' and attribute == 'disable' then
val = true
end
if fieldname == 'global_smwUseStorage' and attribute == 'disable' then
val = true
end
if fieldname == 'global_autocreate_property' and attribute == 'disable' then
val = true
end
end
return val -- this value will be used as new value for field's attribute
end
function Classgenerator.static:sfGenerateForm()
_debug(self, 1, 'entering Classgenerator.static:sfGenerateForm(), from ' .. tostring(self))
local _CFG = self.myConfiguration
local ClassgeneratorParameter = require('Module:Classgenerator/parameter/class')
local ClassSFfield = require('Module:SFfield/class')
local tagStart = '{{{'
local tagEnd = '}}}'
local frame = mw.getCurrentFrame()
-- create the form header
local notification = mw.html.create('')
if _CFG.form.notification and mw.ustring.len(_CFG.form.notification) > 0 then
local mbox = require('Module:Message box')
notification:wikitext(mbox.main('ombox', { text = _CFG.form.notification }))
:newline()
end
local formheader = mw.html.create('')
formheader:wikitext(self:sfGenerateFormInfoTag())
:wikitext('<h2>' .. _CFG.global.entityTitle .. '</h2>')
:tag('p')
:wikitext(_CFG.form.headerText)
:done()
:newline()
:node(notification)
:tag('div')
:attr('id', 'wikiPreview')
:cssText('display: none; padding-bottom: 25px; margin-bottom: 25px; border-bottom: 1px solid #AAAAAA;')
:done()
:newline()
-- create the form buttons
local formbuttons = mw.html.create('div')
for _, button in pairs(_CFG.form.buttons) do
formbuttons:wikitext(tagStart .. 'standard input|' .. button .. tagEnd)
end
formbuttons:addClass('formbuttons')
:done()
-- calculate the fieldlists:
local fieldlists = {}
for _, field in pairs(_CFG.form.fieldOrder) do
local tab = mw.ustring.match(field, '^([a-z]+)_.+')
if not fieldlists[tab] then
fieldlists[tab] = {}
end
table.insert(fieldlists[tab], field)
end
-- assemble everything, so start the html object
local html = mw.html.create('div')
html:node(formheader)
:wikitext('<h1>GLOBAL-Section</h1>')
:newline()
:tag('div')
:wikitext('This section deals with all the class\'s global data, i.e. all data you need for your "template" part as wenn as for your form, ... ')
:done()
:newline()
:wikitext(tagStart .. 'for template|' .. _CFG.template.name .. '|label=' .. _CFG.global.entityTitle .. tagEnd)
:newline()
:node(self:sfGenerateFormTable(fieldlists.global))
:newline()
:wikitext('<h1>FORM-Section</h1>')
:newline()
:tag('div')
:wikitext('This section deals with all the data, you need to create and operate a form for this class. If you don\'t want a form, disable this section. ' ..
'If you need a form (e.g. as part of another form), but no form page, enable this section but leave the field for form page name emtpy.')
:done()
:newline()
:node(self:sfGenerateFormTable(fieldlists.form))
:newline()
:wikitext('<h1>TEMPLATE-Section</h1>')
:newline()
:tag('div')
:wikitext('This section deals with all the data, you need to create and operate a template for this class. If you need tempalte specific parameters ' ..
'(meaning parameteres that you only need to operate the "action"-part), put them into this section\'s custom field')
:done()
:newline()
:node(self:sfGenerateFormTable(fieldlists.template))
:newline()
:wikitext('<h1>PARAMETERS-Section</h1>')
:newline()
:tag('div')
:wikitext('This section deals with all your parameters. You need an entry for every form input field, every template parameter, every data field you want to store, and even every notification line.')
:tag('ul')
:tag('li')
:wikitext("To produce a normal parameter, add an entry, choose storage type, set '''Regular form parameter''' to yes, choose a form input type, and a template doc type.")
:done()
:newline()
:tag('li')
:wikitext("If you want a data field to be stored in your data storage but not defined in the form, choose a data storage type and set '''Regular form parameter''' to no. ")
:done()
:newline()
:tag('li')
:wikitext("If you want a mutiple template to be parsed to a parameter, create a normal parameter (as described above) and choose '''Regular form parameter''' to be ''Holds template''.")
:done()
:newline()
:tag('li')
:wikitext("A parameter with a form input that is not stored is created like a regular parameter but without setting any data storage type.")
:done()
:newline()
:tag('li')
:wikitext("Finally, you can create a message line. This is useful, if you want to convey any information to the user, that is to important for a description-tooltip. " ..
"What you need to do is disable everything ('''Template doc parameter type ''', data storage) and set '''Regular form parameter''' to ''Information''. " ..
"You probalby want to add the parameter to one or more ''show on select'' entries, too.")
:done()
:newline()
:done()
:newline()
:done()
:newline()
:node(self:sfInitField('parameter_parameter'):render())
:newline()
:wikitext(frame:extensionTag('headertabs'))
:newline()
:wikitext("'''(*) Pflichtfeld'''")
:newline()
:wikitext(tagStart .. 'end template' .. tagEnd)
:newline()
:wikitext(ClassgeneratorParameter:sfGenerateForm())
:newline()
:node(formbuttons)
local debugLevel = FoundationClass.globalConfig.debugLevel or self.myConfiguration.global.debugLevel
if debugLevel then
html:newline()
:newline()
:wikitext(ClassDebug:printLog(debugLevel))
end
return html
end
-- **************** declaration of private methods
-- use self.class.myConfiguration to access your configuration in a public or a private method that is called by a public method
_debug = function (self, level, text)
if _private[self] and _private[self].dbg then
local debugLevel = FoundationClass.globalConfig.debugLevel or self.class.myConfiguration.global.debugLevel
if debugLevel and level <= debugLevel then
_private[self].dbg:log(level, text)
end
else
local debugLevel = FoundationClass.globalConfig.debugLevel or self.myConfiguration.global.debugLevel
if debugLevel and level <= debugLevel then
ClassDebug:log(level, text, tostring(self) .. '.static')
end
end
end
local _namespaceName = function (self, namespaceId)
_debug(self, 1, 'entering private _namespaceName() to translate namespace namespaceId ' .. namespaceId .. ' into a universal name, from ' .. tostring(self))
local ret, nulProperty = pcall(mw.title.new, 'NUL', 'Property')
if ret and (namespaceId == nulProperty.namespace) then
return 'property' -- if you change this, check on other places, this is checked against and change that, too
else
return mw.site.namespaces[namespaceId].canonicalName
end
end
local _processAttribute = function (self, attr, indent, name)
_debug(self, 1, 'entering private _processAttribute() to print a line for attribute ' .. attr .. ', from ' .. tostring(self))
local coreData = self:getCoreData()
local attr = attr
local val = coreData[attr]
if type(val) == 'boolean' then
val = val and 'true' or 'false'
end
local ret = ''
local fieldname = mw.ustring.match(attr, '^[^_]+_(.+)$')
ret = indent .. (name and name or fieldname) .. ' = '
if not val then
ret = ret .. 'nil'
elseif type(val) == 'table' then
ret = ret .. Classgenerator.myTableTools.printTable(val, 'inline')
elseif val == 'true' or val == 'false' or mw.ustring.match(val, '^[0-9]+$') or (attr == 'global_gardeningCategory' and val == 'superglobal.gardeningSuperCategory') then
ret = ret .. val
else
ret = ret .. "'" .. mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(val, "\\'", "'"), "'", "\\'"), '\n', '\\n\' ..\n' .. indent .. '\t\'') .. "'" -- the gsub catches multiline input from textareas
end
ret = ret .. ','
if self.class.myConfiguration.template.addCommentsToConfig then
ret = ret .. '\t-- ' .. self.class.myConfiguration.parameter[attr].description
end
ret = ret .. '\n'
return ret
end
local _privateMethod = function (self)
_debug(self, 1, 'entering private _privateMethod() to do something, from ' .. tostring(self))
end
-- **************** declaration of public methods
-- use self.class.myConfiguration to access your configuration in a public method
function Classgenerator:addInfobox()
_debug(self, 1, 'entering Classgenerator:addInfobox(), from ' .. tostring(self))
if self:goodToGo() then
local _CFG = self.class.myConfiguration
local coreData = self:getCoreData()
local usesSmw = FoundationClass.globalConfig.dataStore and (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'smw') and FoundationClass.myYesno(coreData.global_smwUseStorage)
local ib_args = {
bodyclass = 'infobox_name',
aboveclass = 'objtitle titletext',
headerclass = 'headertext',
labelstyle = 'width: 30%;',
datastyle = 'width: 70%;',
title = coreData.className,
subheader = 'Class',
label1 = 'Title',
data1 = coreData.global_entityTitle and coreData.global_entityTitle or '',
label2 = _CFG.parameter.global_edit_timestamp.label,
data2 = coreData.last_edited,
label3 = 'Store available',
data3 = (FoundationClass.globalConfig.dataStore and mw.ustring.len(FoundationClass.globalConfig.dataStore) > 0) and FoundationClass.globalConfig.dataStore or '',
label5 = 'Cargo table',
data5 = (FoundationClass.globalConfig.dataStore and (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'cargo')) and coreData.global_cargoTable or '',
label6 = 'Smw class',
data6 = usesSmw and _private[self].pagename or '',
label7 = 'Namespace',
data7 = coreData.global_namespace and coreData.global_namespace or 'MAIN',
data9 = coreData.global_description,
header10 = 'Pages',
label12 = 'Module',
data12 = _private[self].pagename and '[[Module:' .. _private[self].pagename .. ']]' or '',
label13 = 'Class',
data13 = _private[self].pagename and '[[Module:' .. _private[self].pagename .. '/class]]' or '',
label14 = 'Config',
data14 = _private[self].pagename and '[[Module:' .. _private[self].pagename .. '/config]]' or '',
label17 = 'Template',
data17 = coreData.template_name and '[[Template:' .. coreData.template_name .. ']]' or '',
label19 = 'Form',
data19 = coreData.page.form and '[[:' .. coreData.page.form.name .. ']]' or '',
label21 = 'Category',
data21 = coreData.page.category and '[[:' .. coreData.page.category.name .. ']]' or '',
label22 = 'Gardening',
data22 = coreData.page.gardeningCategory and '[[:' .. coreData.page.gardeningCategory.name .. ']]' or '',
}
if usesSmw and coreData.properties.order and #coreData.properties.order > 0 then
ib_args.header30 = 'Properties'
local i = 31
for _, property in pairs(coreData.properties.order) do
ib_args['label' .. i] = coreData.properties.data[property].type
ib_args['data' .. i] = '[[Property:' .. property .. '|' .. property .. ']]'
i = i + 1
end
end
self:addOutput(require('Module:Infobox').infobox(ib_args))
return true
end
return false
end
function Classgenerator:addPageBody()
_debug(self, 1, 'entering Classgenerator:addPageBody(), from ' .. tostring(self))
_debug(self, 2, ' rendering errors and warnings and adding them to output')
self:addOutput(self:renderErrors())
self:addOutput(self:renderWarnings())
if self:goodToGo() then
local frame = mw.getCurrentFrame()
local lang = mw.language.new('en-gb')
local _CFG = self.class.myConfiguration
local coreData = self:getCoreData()
local imageExtension = require( 'Module:Util' ).globalFileExtension()
-- start
local widthTh = '300px'
local widthTd = '200px'
-- build the page status table
-- first the two status table cells "green" and "red"
local imgYes = '[[File:Yes check' .. imageExtension .. '|13px|alt=Yes|link=]]'
local imgNo = '[[File:X mark' .. imageExtension .. '|13px|alt=No|link=]]'
local tdYa = mw.html.create('td')
tdYa:cssText('background: #90ff90; color:black; vertical-align: middle; text-align: center; width:' .. widthTd)
:addClass('table-yes')
:wikitext(imgYes)
local tdNa = mw.html.create('td')
tdNa:cssText('background: #FF9090; color:black; vertical-align: middle; text-align: center; width:' .. widthTd)
:addClass('table-no')
:wikitext(imgNo)
local classExists = coreData.page.class.exists and coreData.page.config.exists
local modulesExist = coreData.page.base.exists and classExists
local thisClass
local thisConfig
if classExists then
thisClass = require(coreData.page.class.name)
thisConfig = require(coreData.page.config.name)
end
local thisUsesCargo = (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'cargo') and coreData.global_cargoTable and #coreData.global_cargoTable > 0
local thisUsesSmw = (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'smw') and FoundationClass.myYesno(coreData.global_smwUseStorage)
-- write the 2do checklist
local done = true
local step1
local step2
local step3
if modulesExist then
step1 = imgYes .. ' You created all your modules'
else
done = false
step1 = imgNo .. ' You have to create your module pages. This, you have to do <b>manually</b>. Go to [[#Page contents|section Page contents]], copy the module content and edit the corresponding module, ' ..
'pasting all the copied content. Save and close. You have to do this for the following module(s): <ul> ' ..
(not coreData.page.base.exists and '<li>[[#Page contents|' .. coreData.page.base.name .. ']]</li>' or '') ..
(not coreData.page.class.exists and '<li>[[#Page contents|' .. coreData.page.class.name .. ']]</li>' or '') ..
(not coreData.page.config.exists and '<li>[[#Page contents|' .. coreData.page.config.name .. ']]</li>' or '') .. '</ul>'
end
if coreData.page.baseDoc.exists and coreData.page.classDoc.exists and coreData.page.configDoc.exists and coreData.page.template.exists and coreData.page.templateDoc.exists and
(not coreData.page.form or coreData.page.form.exists) and (not coreData.page.category or coreData.page.category.exists) and (not coreData.page.gardeningCategory or coreData.page.gardeningCategory.exists) then
step2 = imgYes .. ' You created all auxilliary pages'
else
done = false
step2 = imgNo .. ' You have to create auxilliary pages. This, you can do <b>automatically</b>. Go to [[#Page autocreation|section Page autocreation]], hit the corresponding "Create"-button or ' ..
'create all pages at once. Please do this for the following page(s): <ul> ' ..
(not (coreData.page.baseDoc.exists or coreData.page.classDoc.exists or coreData.page.configDoc.exists) and '<li>Module documentation pages</li>' or '') ..
(not (coreData.page.template.exists or coreData.page.templateDoc.exists) and '<li>Template and/or template documentation page</li>' or '') ..
((coreData.page.form and not coreData.page.form.exists) and '<li>Form page</li>' or '') ..
(((coreData.page.category and not coreData.page.category.exists) or (coreData.page.gardeningCategory and not coreData.page.gardeningCategory.exists)) and '<li>Category page(s)</li>' or '') .. '</ul>'
end
local storeCargoInstruction
local allPropertiesThere = true
local cargoTableCreateLink = false
if thisUsesCargo then
-- we actually use cargo. check, if cargo table is there or throws an error? if all right, then yes, else instruction above
if modulesExist and coreData.page.template.exists then
cargoTableCreateLink = true
attr = { limit = 1, default = '' }
attr['more results text'] = ''
local tableEntryId = mw.text.trim(mw.text.unstrip(FoundationClass.myCargoUtil.rawquery({tables = coreData.global_cargoTable, fields = {'_ID'}}, attr)))
if mw.ustring.match(mw.text.trim(tableEntryId), '^[0-9]*$') then
storeCargoInstruction = imgYes .. ' Your cargo table does exist! (Note: When you change your cargo table\'s declaration, you need to [[#Page autocreation|rebuild it]], though)'
else
done = false
storeCargoInstruction = imgNo .. ' Please [[#Page autocreation|create your cargo table]]!'
end
else
done = false
storeCargoInstruction = imgNo .. ' To be able to create your cargo table, you have to create the following page(s): <ul>' ..
(not coreData.page.base.exists and '<li>' .. coreData.page.base.name .. '</li>' or '') ..
(not coreData.page.class.exists and '<li>' .. coreData.page.class.name .. '</li>' or '') ..
(not coreData.page.config.exists and '<li>' .. coreData.page.config.name .. '</li>' or '') ..
(not coreData.page.template.exists and '<li>' .. coreData.page.template.name .. '</li>' or '') .. '</ul>'
end
end
if thisUsesSmw then
-- we actually use smw. check, if all properties are present? if all right, then yes, else instruction above
if coreData.properties and coreData.properties.data and FoundationClass.myTableTools.size(coreData.properties.data) > 0 then
for property, propertyData in pairs(coreData.properties.data) do
allPropertiesThere = allPropertiesThere and propertyData.exists
end
if allPropertiesThere then
storeSwmInstruction = imgYes .. ' All your property pages are present and accounted for!'
else
done = false
storeSwmInstruction = imgNo .. ' Please <b>[[#Page autocreation|autocreate]]</b> your properties! The following are missing: <ul>'
for _, property in pairs(coreData.properties.order) do
local pdata = coreData.properties.data[property]
if not pdata or not pdata.exists then
storeSwmInstruction = storeSwmInstruction .. '<li>[[Property:' .. property .. ']]</li>'
end
end
storeSwmInstruction = storeSwmInstruction .. '</ul>'
end
else
done = false
storeSwmInstruction = imgNo .. ' To be able to create your smw properties, you have to create the following page(s): <ul>' ..
(not coreData.page.class.exists and '<li>' .. coreData.page.class.name .. '</li>' or '') ..
(not coreData.page.config.exists and '<li>' .. coreData.page.config.name .. '</li>' or '') .. '</ul>'
end
end
if storeCargoInstruction or storeSwmInstruction then
if storeCargoInstruction and storeSwmInstruction then
step3 = 'Your class used cargo AND smw store. You have to create both data stores: <ul><li>' .. storeCargoInstruction .. '</li><li>' .. storeSwmInstruction .. '</li></ul>'
else
step3 = storeCargoInstruction or storeSwmInstruction
end
else
step3 = imgYes .. ' This class does not use a data store. Nothing to be done here!'
end
local step4 = done and imgYes .. ' You are done. Remember, when you want to change parameters in your config, edit this page and write your [' .. coreData.page.config.editlink .. ' config file] new' or
imgNo .. ' You are not finished yet, please tend to your tasks.'
local manual = mw.html.create('')
manual:wikitext('<h2>Your 2do checklist</h2>')
:tag('ol')
:cssText('margin: 0.3em 0 0 1.6em; padding: 0')
:tag('li')
:wikitext(step1)
:done()
:tag('li')
:wikitext(step2)
:done()
:tag('li')
:wikitext(step3)
:done()
:tag('li')
:wikitext(step4)
:done()
:done()
-- get the data store details, if all the modules exist and we have a datastore configured
local datastore = mw.html.create('')
if thisClass then
datastore:node(thisClass:explainDataStore())
:newline()
end
-- build the status table
local statusTrs = mw.html.create('')
for _, pid in pairs(coreData.page.order) do
statusTrs:tag('tr')
:tag('th')
:css('text-align', 'left')
:css('width', widthTh)
:wikitext(coreData.page[pid].name)
:done()
:newline()
:node(coreData.page[pid].exists and tdYa or tdNa)
:newline()
:done()
:newline()
end
if thisUsesSmw and coreData.properties and coreData.properties.data and FoundationClass.myTableTools.size(coreData.properties.data) > 0 then
statusTrs:tag('tr')
:tag('th')
:css('text-align', 'center')
:css('width', widthTh)
:attr('colspan', 2)
:wikitext('Property pages for your smw store')
:done()
:newline()
for _, property in pairs(coreData.properties.order) do
statusTrs:tag('tr')
:tag('th')
:css('text-align', 'left')
:css('width', widthTh)
:wikitext('Property:' .. property)
:done()
:newline()
:node(coreData.properties.data[property].exists and tdYa or tdNa)
:newline()
:done()
:newline()
end
end
local statusTable = mw.html.create('table')
statusTable:node(statusTrs)
-- page autocreation
local extAutoCreatePage = pcall(frame.callParserFunction, frame, {name = '#createpageifnotex:Module:Classgenerator', args = {'NUL'}})
local autoCreation = _CFG.template.createPages and extAutoCreatePage
local pageAutoCreation = mw.html.create('')
pageAutoCreation:wikitext('<h2>Page autocreation</h2>')
:newline()
if autoCreation then
-- depending on parameters and existence of pages do the autocreate or print the button
-- first see, which pagecomplexes (modules(docs), templates, form, category) are missing
local missing = {}
-- in missing we store, if a page in a given namespace is missing. Namespaces are stored by their ids (numbers)
for _, pid in pairs(coreData.page.order) do
-- due to extension autocreatepage messing up module pages, in namepace module we only autocreate doc pages
if not coreData.page[pid].exists and not Classgenerator.myTableTools.inTable(missing, coreData.page[pid].namespace) and
(coreData.page[pid].namespace ~= 828 or coreData.page[pid].isDocPage) then
table.insert(missing, coreData.page[pid].namespace)
end
end
if thisUsesSmw and not allPropertiesThere then
table.insert(missing, mw.title.new('NUL', 'Property').namespace)
end
-- now generate the printout or call the parser function depending on global_autocreate_* status
-- remember the switches 'global_autocreate_module', 'global_autocreate_template', 'global_autocreate_form', 'global_autocreate_category', and 'global_autocreate_property'
local actable = mw.html.create('table')
for _, nsid in pairs(missing) do
local ns = mw.ustring.lower(_namespaceName(self, nsid))
local information = ''
if coreData.autocreate[ns] and coreData.autocreate[ns] > os.time() - _CFG.template.autoCreationTimeDiff then
-- ************************************* actual autocreation is done here
-- we iterate over all namespaces for which pages are missing (var missing) and spring into action, if we have a numeric value supplied for that namespace coreData.autocreate[ns] that is recent enough
-- now we have a namespace, we want to create pages for (var nsid) (all that is done in the recent 4 lines). what we do in the following lines:
-- we iterate over all pages in coreData.page.order and spring into action, if the interation instance (pid) is in the namespace (nsid), the page is non exist and is not a module
-- in that action body, we create the page with the precalcualted content
-- also: for convenience, we create some global project (meta)categories, if related to the current page (project-form-category if nsid for forms, etc.) and configured in Foundationclass/globalconfig. here is an overview
-- Classgenerator.globalConfig.formCategory : MediaWiki:Classengine-content-project-form-category
-- Classgenerator.globalConfig.gardeningSuperCategory : MediaWiki:Classengine-content-project-gardening-supercategory
-- Classgenerator.globalConfig.moduleCategory : MediaWiki:Classengine-content-project-module-category
-- Classgenerator.globalConfig.projectSuperCategory : MediaWiki:Classengine-content-project-supercategory
-- Classgenerator.globalConfig.propertyCategory : MediaWiki:Classengine-content-project-property-category
-- Classgenerator.globalConfig.templateCategory : MediaWiki:Classengine-content-project-templates
for _, pid in pairs(coreData.page.order) do
_debug(self, 3, ' testing page "' .. coreData.page[pid].name .. '": namespace id is ' .. coreData.page[pid].namespace ..
', and page does ' ..(not coreData.page[pid].exists and 'not ' or '') .. 'exist')
if coreData.page[pid].namespace == nsid and not coreData.page[pid].exists and (nsid ~= 828 or coreData.page[pid].isDocPage) then
if pid == 'gardeningCategory' and Classgenerator.globalConfig.gardeningSuperCategory and #Classgenerator.globalConfig.gardeningSuperCategory > 0 then
-- we just iterated over the gardening category page (so this class has one) but we did not create it, yet)
-- blindly try to create the gardening supercategory first, in case the class's gardening category is the gardening supercategory, we dont want the class specific content
local content = '{{MediaWiki:Classengine-content-project-gardening-supercategory}}'
_debug(self, 3, ' trying to autocreate garderning supercategory page "' .. Classgenerator.globalConfig.gardeningSuperCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.gardeningSuperCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
end
-- here we actually create the missing page. THIS IS CORE FEATURE :)
_debug(self, 3, ' trying to autocreate page "' .. coreData.page[pid].name .. '" with # of content being ' .. #coreData.page[pid].content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:' .. coreData.page[pid].name, args = { frame:preprocess(coreData.page[pid].content) } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
if pid == 'form' and Classgenerator.globalConfig.formCategory and #Classgenerator.globalConfig.formCategory > 0 then
-- we just iterated over the form page (so this class has one) and created it (yay). Now blindly create the formCategory as well...
local content = '{{MediaWiki:Classengine-content-project-form-category}}'
_debug(self, 3, ' trying to autocreate form category page "' .. Classgenerator.globalConfig.formCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.formCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
elseif nsid == 828 and Classgenerator.globalConfig.moduleCategory and #Classgenerator.globalConfig.moduleCategory > 0 then
-- we just iterated a module doc page (so this class has one) and created it (yay). Now blindly create the moduleCategory as well...
local content = '{{MediaWiki:Classengine-content-project-module-category}}'
_debug(self, 3, ' trying to autocreate module category page "' .. Classgenerator.globalConfig.moduleCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.moduleCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
elseif pid == 'category' and Classgenerator.globalConfig.projectSuperCategory and #Classgenerator.globalConfig.projectSuperCategory > 0 then
-- we just iterated over the category page (so this class has one) and created it (yay). Now blindly create the supercategory as well...
local content = '{{MediaWiki:Classengine-content-project-supercategory}}'
_debug(self, 3, ' trying to autocreate super category page "' .. Classgenerator.globalConfig.projectSuperCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.projectSuperCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
elseif nsid == 10 and Classgenerator.globalConfig.templateCategory and #Classgenerator.globalConfig.templateCategory > 0 then
-- we just iterated over a page in template namespace (so this class has one) and created it (yay). Now blindly create the templateCategory as well...
local content = '{{MediaWiki:Classengine-content-project-template-category}}'
_debug(self, 3, ' trying to autocreate template category page "' .. Classgenerator.globalConfig.templateCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.templateCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
end
end
end
if thisUsesSmw and (nsid == mw.title.new('NUL', 'Property').namespace) and coreData.properties.data then
-- add here autocreation of properties
for property, pdata in pairs(coreData.properties.data) do
if not pdata.exists then
local content = pdata.content
_debug(self, 3, ' trying to autocreate property page "' .. property .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Property:' .. property, args = { frame:preprocess(pdata.content) } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
end
end
-- we just iterated over all missing property pages (so this class has some) and created them (yay). Now blindly create the propertyCategory as well...
local content = '{{MediaWiki:Classengine-content-project-property-category}}'
_debug(self, 3, ' trying to autocreate property category page "' .. Classgenerator.globalConfig.propertyCategory .. '" with # of content being ' .. #content)
local ret = frame:callParserFunction{ name = '#createpageifnotex:Category:' .. Classgenerator.globalConfig.propertyCategory, args = { content } }
if #ret > 0 then
information = information .. '<br>' .. ret .. '\n'
end
end
end
-- create the tr for the ns
actable:tag('tr')
:tag('th')
:css('text-align', 'left')
:css('width', widthTh)
:wikitext('Create ' .. ((nsid == 828 and 'module docs' or (ns == 'property' and 'properties' or (ns .. (ns == 'template' and 's' or '')))) .. ':'))
-- note: nsid == mw.title.new('NUL', 'Property').namespace is necessary since canonicalname for property namespace does not translate uniquely over different languages :(
:done()
:newline()
:tag('td')
:cssText('color:black; vertical-align: middle; text-align: center; width:' .. widthTd)
:css('background', (coreData.autocreate[ns] and coreData.autocreate[ns] > os.time() - _CFG.template.autoCreationTimeDiff) and '#90ff90' or '#FF9090' )
:wikitext(frame:callParserFunction{name = '#autoedit', args={form='Classgenerator', target=self:getUid(),
'link text=' .. (coreData.autocreate[ns] and 'Requested on ' .. os.date('%d.%m.%Y %X', coreData.autocreate[ns]) or 'Create automatically!') ..
(#information > 0 and ('Call returned ' .. information) or ''),
'reload', summary="Requesting the autocreation of " .. coreData.className .. ' for pages of type ' .. ns,
'query string=Classgenerator[global_autocreate_' .. ns .. ']=' .. os.time()}
})
:done()
:newline()
:done()
:newline()
end
if Classgenerator.myTableTools.size(missing) > 0 then
-- show the all button
local querystring = ''
for _, nsid in pairs(missing) do
local ns = mw.ustring.lower(_namespaceName(self, nsid))
querystring = querystring .. 'Classgenerator[global_autocreate_' .. ns .. ']=' .. os.time() .. '&'
end
querystring = mw.ustring.sub(querystring, 1, -2)
actable:tag('tr')
:tag('th')
:css('text-align', 'left')
:css('width', widthTh)
:wikitext('Create all pages:')
:done()
:newline()
:tag('td')
:cssText('background: #FF9090; color:black; vertical-align: middle; text-align: center; width:' .. widthTd)
:wikitext(frame:callParserFunction{name = '#autoedit', args={form='Classgenerator', target=self:getUid(),
'link text=Create automatically!', 'reload', summary="Requesting the autocreation of all missing pages", 'query string=' .. querystring }
})
:done()
:newline()
:done()
:newline()
pageAutoCreation:wikitext('<b>Note:</b> Creation of module pages is impossible due to an incompatibility issue.')
:newline()
:node(actable)
:newline()
else
pageAutoCreation:wikitext('All pages present!')
:newline()
:tag('p')
:wikitext('<small><b>Note:</b> Creation of module pages is impossible due to an incompatibility issue.</small>')
:newline()
:done()
:newline()
end
else
pageAutoCreation:wikitext('Page autocreation is only possible if activated in your [[Module:Classgenerator/config]]-file (see template-section) and '
.. 'Extension AutoCreatePage being installed.')
:newline()
end
if cargoTableCreateLink then
pageAutoCreation:wikitext('<b>Cargo data store:</b>To (re-)create your cargo table, follow <span class="plainlinks">[' .. coreData.page.template.recreatedata .. ' this link]</span> and then press ok!')
:newline()
end
-- build the content collapses
local collapse = require('Module:Collapse').main
local bg_sets = { exist = {'#cfc', '#9c9'}, nonexist = {'#fcc', '#c99'} }
local bg = 1
local pageContent = mw.html.create('')
for _, pid in pairs(coreData.page.order) do
local content
local bgs = coreData.page[pid].exists and bg_sets.exist or bg_sets.nonexist
if coreData.page[pid].namespace == 828 and not coreData.page[pid].isDocPage then
content = frame:expandTemplate{ title = 'Code', args = {lang = 'lua', code = coreData.page[pid].content, line = '1'}}
else
content = '<pre style="white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; white-space:pre-wrap; word-wrap:break-word;">' ..
mw.text.nowiki(frame:preprocess(coreData.page[pid].content)) .. '</pre>'
end
pageContent:wikitext(collapse({ header = 'Contents of <b>[[:' .. coreData.page[pid].name .. ']]</b> ' ..
'<span class="plainlinks" style="font-size:75%;">[[' .. coreData.page[pid].editlink ..
' EDIT]]</span>',
content = content, left = true, bg = bgs[bg]
}))
:newline()
bg = (bg == 2 and 1 or 2)
end
if thisUsesSmw and coreData.properties.order then
-- add here the collpases of the properties
pageContent:tag('p')
:wikitext('<h3>All property pages</h3>')
:done()
for _, property in pairs(coreData.properties.order) do
local bgs = coreData.properties.data[property].exists and bg_sets.exist or bg_sets.nonexist
local content = '<pre style="white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; white-space:pre-wrap; word-wrap:break-word;">' ..
mw.text.nowiki(frame:preprocess(coreData.properties.data[property].content)) .. '</pre>'
pageContent:wikitext(collapse({ header = 'Contents of <b>[[:Property:' .. property .. ']]</b> ' ..
'<span class="plainlinks" style="font-size:75%;">[[' .. coreData.properties.data[property].editlink ..
' EDIT]]</span>',
content = content, left = true, bg = bgs[bg]
}))
:newline()
bg = (bg == 2 and 1 or 2)
end
end
local updateWarning = mw.html.create('')
if coreData.now_timestamp - coreData.edit_timestamp < 2*60*60 then
local mbox = require('Module:Message box')
updateWarning:wikitext(mbox.main('ombox', { type='content', text = 'Note: You updated the class ' .. coreData.edit_time_before .. ' ago. Did you write your [[#Page contents|config file]] new? ' ..
'Changes won\'t take effect unless you do!' .. ((thisUsesCargo and cargoTableCreateLink) and '<p><span class="plainlinks">Also: If you changed your cargo table\'s declaration, [' ..
coreData.page.template.editlink .. ' edit your template] and [[#Page autocreation|rebuild your cargo table]]!</span>' or '')}))
:newline()
end
local smwPropertyHint = mw.html.create('')
if (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'smw')
and FoundationClass.myYesno(coreData.global_smwUseStorage)
and not coreData.properties.order then
local mbox = require('Module:Message box')
smwPropertyHint:wikitext(mbox.main('ombox', { type='notice', text = 'Hint: If you use properties in your class, they will not display in <i>Page contents</i>, nor be listed in <i>Page status</i> or '
.. 'autocreated in <i>Page autocreation</i> unless you have your class and config page created!'}))
:newline()
end
-- assemble everything
local html = mw.html.create('')
html:wikitext(coreData.global_description)
:newline()
:node(updateWarning)
:node(smwPropertyHint)
:node(manual)
:newline()
:node(datastore)
:wikitext('<h2>Page status</h2>')
:newline()
:wikitext(autoCreation and 'This status may be inaccurate, if you just created pages. In that case, run jobs and clear cache of this page.' or '')
:node(statusTable)
:newline()
:node(pageAutoCreation)
:wikitext('<h2>Page contents</h2>')
:newline()
:node(pageContent)
:newline()
:done()
local debugLevel = FoundationClass.globalConfig.debugLevel or _CFG.global.debugLevel
if debugLevel then
html:tag('pre')
-- :wikitext(FoundationClass.myTableTools.printTable(coreData))
-- :wikitext(FoundationClass.myTableTools.printTable(thisClass:smwProperty2ParameterTranslationTable()))
:wikitext(ClassDebug:printLog(debugLevel))
:done()
end
self:addOutput(html)
return true
end
return false
end
function Classgenerator:myArgumentProcessing(coreData)
_debug(self, 1, 'entering Classgenerator:myArgumentProcessing(args) to process coreData, from ' .. tostring(self))
-- function that performs some individual transformation args --&gt; coreData
local _CFG = self.class.myConfiguration
local coreData = coreData
local lang = mw.language.new('en')
coreData.className = lang:ucfirst(mw.text.trim(mw.ustring.gsub(self:getUid(), ':', '')))
coreData.edit_timestamp = lang:formatDate('U', coreData.global_edit_timestamp)
coreData.now_timestamp = lang:formatDate('U') + 60*60
coreData.edit_time_before = lang:formatDuration(coreData.now_timestamp-coreData.edit_timestamp)
coreData.last_edited = lang:formatDate('d.m.Y H:i:s', coreData.global_edit_timestamp)
if coreData.global_gardeningCategory_chooser and mw.ustring.lower(coreData.global_gardeningCategory_chooser) == 'global' then
coreData.global_gardeningCategory = 'superglobal.gardeningSuperCategory'
end
if mw.ustring.find(coreData.className, '[ /]', 1) then
local tmp = ''
for fragment in mw.text.gsplit(coreData.className, '[ /]') do
tmp = tmp .. lang:ucfirst(fragment)
end
coreData.className = tmp
end
if coreData.global_cargoTable then
coreData.global_cargoTable = mw.ustring.gsub(mw.ustring.lower(coreData.global_cargoTable), ' ', '_')
end
if coreData.form_createInfotext and #coreData.form_createInfotext > 0 and mw.ustring.sub(coreData.form_createInfotext, -1) ~= ' ' then
coreData.form_createInfotext = coreData.form_createInfotext .. ' '
end
local parameter_parameter
local fieldOrder
if coreData.parameter_parameter then
parameters = ''
fieldOrder = {}
local classGenParamConfig = mw.loadData('Module:Classgenerator/parameter/config')
for result in mw.text.gsplit(coreData.parameter_parameter, classGenParamConfig.template.delimiterResult, true) do
local fieldname, parameter = mw.ustring.match(result, '^([^#]*)' .. classGenParamConfig.template.delimiterFormFieldName .. '(.+)$')
if fieldname and mw.ustring.len(mw.text.trim(fieldname)) > 0 then
table.insert(fieldOrder, mw.text.trim(fieldname))
end
if parameter and mw.ustring.len(parameter) > 0 then
parameters = parameters .. parameter
end
end
end
coreData.parameter_parameter = parameters
coreData.form_enable = FoundationClass.myYesno(coreData.form_enable)
if coreData.form_enable then
coreData.form_fieldOrder = fieldOrder
form_buttons = { 'save' }
if coreData.form_buttons and #coreData.form_buttons > 0 then
for _, button in pairs(coreData.form_buttons) do
table.insert(form_buttons, button)
end
end
table.insert(form_buttons, 'cancel')
end
coreData.form_buttons = form_buttons
-- here build the class config
local contentClassConfig = mw.ustring.gsub(_CFG.template.configIntro, _CFG.template.placeHolderClassName, coreData.className) ..
'local global = {\n' ..
'\tdebugLevel = false,'
if self.class.myConfiguration.template.addCommentsToConfig then
contentClassConfig = contentClassConfig .. '\t-- set this to the level you wish to display at render. false if disabled. this is a class based setting. ' ..
'you can set this globally at Foundationclass/globalconfig, causing all child classes to debug.'
end
contentClassConfig = contentClassConfig .. '\n'
-- calculate the fieldlists:
local fieldlists = {}
for _, field in pairs(_CFG.form.fieldOrder) do
local tab = mw.ustring.match(field, '^([a-z]+)_.+')
if not fieldlists[tab] then
fieldlists[tab] = {}
end
table.insert(fieldlists[tab], field)
end
local omissionList = {'global_autocreate_module', 'global_autocreate_template', 'global_autocreate_form', 'global_autocreate_category', 'global_autocreate_property', 'global_edit_timestamp', 'global_gardeningCategory_chooser',
'form_textareaAttributes_cols', 'form_textareaAttributes_rows', 'form_textareaAttributes_autogrow', 'form_textareaAttributes_editor', 'form_createLinkInfo',
'global_customization', 'form_customization', 'template_customization' }
for _, attr in pairs(fieldlists.global) do
if not Classgenerator.myTableTools.inTable(omissionList, attr) and self.class.myConfiguration.parameter[attr] then
contentClassConfig = contentClassConfig .. _processAttribute(self, attr, '\t')
end
end
if coreData.global_customization then
for line in mw.text.gsplit(coreData.global_customization, '\n', true) do
contentClassConfig = contentClassConfig .. '\t' .. line .. '\n'
end
end
contentClassConfig = contentClassConfig .. '}\n\nlocal form = {\n'
for _, attr in pairs(fieldlists.form) do
if not Classgenerator.myTableTools.inTable(omissionList, attr) and self.class.myConfiguration.parameter[attr] then
contentClassConfig = contentClassConfig .. _processAttribute(self, attr, '\t')
end
end
contentClassConfig = contentClassConfig .. '\ttextareaAttributes = { -- the defaults for your textarea fields\n'
for _, attr in pairs({'form_textareaAttributes_cols', 'form_textareaAttributes_rows', 'form_textareaAttributes_autogrow', 'form_textareaAttributes_editor'}) do
local name = mw.ustring.match(attr, '^form_textareaAttributes_(.+)$')
contentClassConfig = contentClassConfig .. _processAttribute(self, attr, '\t\t', name)
end
contentClassConfig = contentClassConfig .. '\t},\n'
contentClassConfig = contentClassConfig .. _processAttribute(self, 'form_fieldOrder', '\t')
if coreData.form_customization then
for line in mw.text.gsplit(coreData.form_customization, '\n', true) do
contentClassConfig = contentClassConfig .. '\t' .. line .. '\n'
end
end
contentClassConfig = contentClassConfig .. '}\n\nlocal template = {\n'
for _, attr in pairs(fieldlists.template) do
if not Classgenerator.myTableTools.inTable(omissionList, attr) and self.class.myConfiguration.parameter[attr] then
contentClassConfig = contentClassConfig .. _processAttribute(self, attr, '\t')
end
end
if coreData.template_customization then
for line in mw.text.gsplit(coreData.template_customization, '\n', true) do
contentClassConfig = contentClassConfig .. '\t' .. mw.text.trim(line) .. '\n'
end
end
contentClassConfig = contentClassConfig .. '}\n\nlocal parameter = {\n' .. coreData.parameter_parameter .. '}\n\n' ..
'return {\n' ..
'\tform = form,\n' ..
'\tglobal = global,\n' ..
'\tparameter = parameter,\n' ..
'\ttemplate = template,\n}\n'
local classCategory = Classgenerator.globalConfig.classCategory or 'none'
local formCategory = Classgenerator.globalConfig.formCategory or 'none'
local gardeningCategory = Classgenerator.globalConfig.gardeningSuperCategory or 'none'
local moduleCategory = Classgenerator.globalConfig.moduleCategory or 'none'
local propertyCategory = Classgenerator.globalConfig.propertyCategory or 'none'
local superCategory = Classgenerator.globalConfig.projectSuperCategory or 'none'
local templateCategory = Classgenerator.globalConfig.templateCategory or 'none'
local page = {}
page.order = {'base', 'baseDoc', 'class', 'classDoc', 'config', 'configDoc', 'template', 'templateDoc'}
page.base = {
name = 'Module:' .. _private[self].pagename,
content = mw.message.new('classengine-template-module-page'):rawParams(_private[self].pagename):plain()
}
page.baseDoc = {
name = 'Module:' .. _private[self].pagename .. '/doc',
content = mw.message.new('classengine-template-module-documentation-page'):rawParams(_private[self].pagename, moduleCategory):plain()
}
page.class = {
name = 'Module:' .. _private[self].pagename .. '/class',
content = mw.message.new('classengine-template-module-class-page'):rawParams(_private[self].pagename, coreData.className):plain()
}
page.classDoc = {
name = 'Module:' .. _private[self].pagename .. '/class/doc',
content = mw.message.new('classengine-template-module-class-documentation-page'):rawParams(_private[self].pagename, coreData.className, moduleCategory, classCategory):plain()
}
page.config = {
name = 'Module:' .. _private[self].pagename .. '/config',
content = contentClassConfig,
}
page.configDoc = {
name = 'Module:' .. _private[self].pagename .. '/config/doc',
content = mw.message.new('classengine-template-module-config-documentation-page'):rawParams(_private[self].pagename, moduleCategory, classCategory):plain()
}
page.template = {
name = 'Template:' .. coreData.template_name,
content = mw.message.new('classengine-template-template-page'):rawParams(_private[self].pagename):plain()
}
page.templateDoc = {
name = 'Template:' .. coreData.template_name .. '/doc',
content = mw.message.new('classengine-template-template-documentation-page'):rawParams(_private[self].pagename, templateCategory):plain()
}
if coreData.form_name and #coreData.form_name > 0 then
table.insert(page.order, 'form')
page.form = {
name = 'Form:' .. coreData.form_name,
content = mw.message.new('classengine-template-form-page'):rawParams(_private[self].pagename, formCategory):plain()
}
end
if coreData.global_category and #coreData.global_category> 0 then
table.insert(page.order, 'category')
page.category = {
name = 'Category:' .. coreData.global_category,
content = mw.message.new('classengine-template-category-page'):rawParams(_private[self].pagename, superCategory):plain()
}
end
if coreData.global_gardeningCategory and #coreData.global_gardeningCategory > 0 then
table.insert(page.order, 'gardeningCategory')
local pagename = coreData.global_gardeningCategory
if pagename == 'superglobal.gardeningSuperCategory' then
pagename = FoundationClass.globalConfig.gardeningSuperCategory
end
page.gardeningCategory = {
name = 'Category:' .. pagename,
content = mw.message.new('classengine-template-gardeningcategory-page'):rawParams(_private[self].pagename, gardeningCategory):plain()
}
end
for _, pid in pairs(page.order) do
local obj = mw.title.new(page[pid].name)
page[pid].exists = obj.exists
page[pid].namespace = obj.namespace
page[pid].editlink = obj:fullUrl{action='edit'}
if pid == 'template' then
page[pid].recreatedata = obj:fullUrl{action='recreatedata'}
end
page[pid].isDocPage = (mw.ustring.sub(page[pid].name, -4) == '/doc')
if page[pid].isDocPage then
page[pid].content = page[pid].content .. '<h2>Maintenanace notes</h2>\n' ..
'This page was created by [[Module:Classgenerator]] and belongs to [[' .. self:getUid() .. ']].\n'
if pid == 'configDoc' then
page[pid].content = page[pid].content .. '\n{{((}}ombox| type=content | text = It is strongly advised, to not edit this page but to use [' ..
'https://{{((}}SERVERNAME{{))}}{{((}}SCRIPTPATH{{))}}/Special:FormEdit/Classgenerator/' .. mw.uri.encode(self:getUid(), "PATH") .. ' ' ..
'the Classgenerator form] instead! After that, use your new configuration to replace the contents of this page.{{))}}'
end
end
end
local thisClass
local thisConfig
if page.class.exists and page.config.exists then
thisClass = require(page.class.name)
thisConfig = require(page.config.name)
end
if page.form and (not coreData.form_typeCreateLink or coreData.form_typeCreateLink ~= 'forminput') and coreData.form_createLinkPageName and mw.ustring.len(coreData.form_createLinkPageName) > 0 then
local pageName = coreData.form_createLinkPageName
if coreData.global_namespace and mw.ustring.len(coreData.global_namespace) > 0 and not mw.ustring.match(pageName, '^' .. coreData.global_namespace .. ':.+$') then
pageName = coreData.global_namespace .. ':' .. pageName
end
local infostr = '{{((}}{info|page name=' .. pageName .. '|add title=' .. (coreData.form_labelCreate or 'create entity') .. '|edit title=' .. (coreData.form_labelEdit or 'edit entity') .. '}{{))}}'
page.form.content = page.form.content .. '<!{{#invoke:String|rep|-|2}} this is a workaround, needed because of a SF bug: ' .. infostr ..
'. see https://phabricator.wikimedia.org/T123230 for more information {{#invoke:String|rep|-|2}}>'
end
coreData.page = page
local autocreate = {}
autocreate.module = FoundationClass.myYesno(coreData.global_autocreate_module, tonumber(coreData.global_autocreate_module))
autocreate.template = FoundationClass.myYesno(coreData.global_autocreate_template, tonumber(coreData.global_autocreate_template))
autocreate.form = coreData.form_name and FoundationClass.myYesno(coreData.global_autocreate_form, tonumber(coreData.global_autocreate_form))
autocreate.category = (coreData.global_category or coreData.global_gardeningCategory) and FoundationClass.myYesno(coreData.global_autocreate_category, tonumber(coreData.global_autocreate_category))
if (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'smw') and FoundationClass.myYesno(coreData.global_smwUseStorage) then
local propertyNSName = _namespaceName(self, mw.title.new('NUL', 'Property').namespace)
autocreate[propertyNSName] = FoundationClass.myYesno(coreData['global_autocreate_' .. propertyNSName], tonumber(coreData['global_autocreate_' .. propertyNSName]))
end
coreData.autocreate = autocreate
local propertyData
local propertyOrder
if (FoundationClass.globalConfig.dataStore == 'both' or FoundationClass.globalConfig.dataStore == 'smw') and FoundationClass.myYesno(coreData.global_smwUseStorage) and thisClass and thisConfig and thisConfig.global.smwUseStorage then
-- we use smw and class and config are created and accessible. we can get property information and prepare data
local matrix = thisClass:smwGetProperty2ParameterTranslationTable()
propertyData = {}
propertyOrder = {}
for prop, parameter in pairs(matrix) do
if FoundationClass.globalConfig.ucfirst then
property = lang:ucfirst(prop)
else
property = prop
end
table.insert(propertyOrder, property)
local obj = mw.title.new(property, 'Property')
propertyData[property] = {
editlink = obj:fullUrl{action='edit'},
exists = obj.exists,
parameter = parameter,
}
if thisConfig.parameter[parameter] then
propertyData[property].description = thisConfig.parameter[parameter].description
propertyData[property].type = thisConfig.parameter[parameter].property_type
propertyData[property].values = thisConfig.parameter[parameter].values
elseif parameter == FoundationClass.globalConfig.smwClassProperty then
propertyData[property].description = 'Automatisch hinzugefügt! Wird verwendet, um Mitglieder dieser Klasse zu finden (funktioniert auch, ohne dass eine Kategorie definiert wird und auch fur subobjects)'
propertyData[property].type = 'Text'
elseif parameter == FoundationClass.globalConfig.uidFieldName then
propertyData[property].description = 'Automatisch hinzugefügt! Wird verwendet, um individuelle Objekte innerhalb der Klasse zu identifizieren.'
propertyData[property].type = 'Text'
end
local values = ''
if propertyData[property].values then
values = values .. 'The allowed values are:'
for _, value in pairs(propertyData[property].values) do
values = values .. '\n* [[Allows value::' .. value .. ']]'
end
else
values = 'No restriction given'
end
propertyData[property].content = mw.message.new('classengine-template-property-page'):rawParams(propertyData[property].description, propertyData[property].type, values, _private[self].pagename, propertyCategory):plain()
end
table.sort(propertyOrder)
end
coreData.properties = { data = propertyData, order = propertyOrder }
return coreData -- this is your new coreData.
end
function Classgenerator:myPlausibilityTest(args)
_debug(self, 1, 'entering Classgenerator:myPlausibilityTest(args) to test arguments, from ' .. tostring(self))
-- function that performs the individual plausibility tests
-- note: before you access a field args.fieldname you should check for existance
-- self:addError(text)
return false -- return value will be ignored. but if you add any error, the object's initialization will fail with the error
end
function Classgenerator:myStashAdjustments(stash)
_debug(self, 1, 'entering Classgenerator:myStashAdjustments(stash) to do some minor adjustments on data before storing, from ' .. tostring(self))
-- function that alters the stash before storing the data
local stash = stash
return stash -- this is your new stash. this will be stored. it has format (fieldname: value)
end
function Classgenerator:method()
_debug(self, 1, 'entering Classgenerator:method() to do something, from ' .. tostring(self))
return true
end
return Classgenerator