Modul:Foundationclass/doc
This is a documentation subpage for Modul:Foundationclass. It contains usage information, categories and other content that is not part of the original modul page. |
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 Template for Class Modules. It implements a class in Lua using Module:Middleclass and provides serveral static and public methods, commonly used in the typical form>page>store process.
Usage
This is in a way an abstract class. It provides some static and public methods for resuse, and also maintains a store of private properties. If can be used to fast and easily create a typical class module that can handle:
- creating an appropriate form
- supplying your respective template with functionalities for
- object initialization via template parameters, arguments, and datastore (self initialization)
- general data assesment (basic plausibility tests)
- data storage (supported are cargo and semantic media wiki)
- error and warnings management
- output and rendering
- creating a template documentation
You can and should adjust the module in this methods:
- individual attribute adjustment for the semantic forms fields
- individual plausibility testing
- individual data initialization
- individual data store adjustments before stashing
You can access the objects core data store with getCoreData() and its uid with getUid().
How-To
This is, what you have to do (see Useful templates for content of the corresponding pages):
- create your base module Module:Name
- create your class module Module:Name/class. For this, copy lua sample code below this list and apply the following changes:
- change all occurences of className into your class name
- change the highlighted lines and replace 'Name' with the Name of your module
- implement the abstract methods:
- myAgumentProcessing(coreData)
- myDataAdjustments(data)
- myPlausibilityTest(args)
- myStashAdjustments(stash)
- static:mySfDynamicFieldAttribute(fieldname, attribute, value)
- for the usual output generation, implement (shells given in sample code)
- addInfobox()
- addPageBody()
- create and fill your configuration Module:Name/config
- create your template Template:Name
- create your form Form:Name
- if applicable, create your category page Category:Name
- fill in documentation:
- of your base module (place one invoke below the first comment and before the includeonly)
- of your class module (new docu for your own public, static and private methods (which you can probably copy from other classes) and one invoke to show the inheritance. Sample code provided in Useful templates
- of your class module's configuration (just copy content)
- of your template (one invoke below the first comment and before the includeonly)
Useful templates
base module: |
---|
local p = {}
local Class = require('Module:Name/class')
local getArgs = require('Module:Arguments').getArgs
function p.categorize(frame)
return tostring(Class:categorize())
end
function p.categoryPage(frame)
return tostring(Class:categoryPage())
end
function p.explainDataStore(frame)
return tostring(Class:explainDataStore())
end
function p.gardeningCategoryPage(frame)
return tostring(Class:gardeningCategoryPage())
end
function p.sfGenerateForm(frame)
return tostring(Class:sfGenerateForm())
end
function p.sfGenerateFormEntry(frame)
return tostring(Class:sfGenerateFormEntry())
end
function p.sfGenerateFormLink(frame)
return tostring(Class:sfGenerateFormLink())
end
function p.templateDocumentation(frame)
return tostring(Class:templateDocumentation())
end
function p.main(frame)
local args = getArgs(frame)
local me = Class:new(mw.title.getCurrentTitle().prefixedText)
me:initFromArgs(args)
me:storeData()
me:addInfobox()
me:addPageBody()
return me:render()
end
return p
|
base module's documentation page: |
---|
{{documentation subpage}} {{module rating|protected}} <!-- Categories go at the bottom of this page and interwikis go in Wikidata. --> This module implements template {{tl|Name}}. == Usage == {{pre| {{tli|Name|''main''}} }} It also provides some additional "gateways" to some of [[Module:Name/class]]'s static methods: {{pre| {{tli|Name|''categorize''}} {{tli|Name|''categoryPage''}} {{tli|Name|''explainDataStore''}} {{tli|Name|''gardeningCategoryPage''}} {{tli|Name|''sfGenerateForm''}} {{tli|Name|''sfGenerateFormEntry''}} {{tli|Name|''sfGenerateFormLink''}} {{tli|Name|''templateDocumentation''}} }} {{#invoke:Name|categorize}}<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox|| <!-- Note: The class engine sets the category "Project modules" automatically in function categorize --> <!-- Categories go here if you wish an additional category to that set in {{module rating}} above automatically. --> }}</includeonly> |
class module: |
---|
local FoundationClass = require('Module:Foundationclass')
local ClassDebug = require('Module:Debug/class')
-- ****************************************************************
-- * inheritance *
-- ****************************************************************
local ClassName = FoundationClass:subclass('Name')
-- setting class's configuration data
ClassName.static.myConfiguration = mw.loadData('Module:Name/config') -- this means, modules on subpages have a / in their names
-- 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
-- ClassName.static.myPropertyModule = require('Module:extern')
-- ClassName.static.staticProperty = ' '
-- remember the static classes provided by Foundationclass:
-- ClassName.globalConfig
-- ClassName.myCargoUtil
-- ClassName.mySmwUtil
-- ClassName.myTableTools
-- ClassName.myYesno
-- **************** 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 ClassName:initialize(uid, superhandler)
local _CFG = self.class.myConfiguration
FoundationClass.initialize(self, uid, superhandler)
_private[self] = {
dbg = ClassDebug:new(tostring(self.class) .. ': id ' .. uid),
}
_debug(self, 1, ' ClassName: done initializing object "' .. uid ..'", from ' .. tostring(self))
end
-- use use self.myConfiguration to access your configuration in a static method
function ClassName.static:aStaticMethod(var)
_debug(self, 1, 'entering ClassName.static:aStaticMethod() to do something, from ' .. tostring(self))
end
function ClassName.static:mySfDynamicFieldAttribute(fieldname, attribute, value)
_debug(self, 1, 'entering ClassName.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".
-- however, this causes the parameter to not show at all, neither in the form, nor in processing
local val = value
if fieldname == 'this' and attribute == 'that' then
val = 'whatever ' .. val
end
return val -- this value will be used as new value for field's attribute
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 _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 ClassName:addInfobox()
_debug(self, 1, 'entering ClassName:addInfobox(), from ' .. tostring(self))
if self:goodToGo() then
local _CFG = self.class.myConfiguration
local coreData = self:getCoreData()
local ib_args = {
bodyclass = 'infobox_name',
aboveclass = 'objtitle titletext',
headerclass = 'headertext',
labelstyle = 'width: 30%;',
datastyle = 'width: 70%;',
title = self:getUid(),
subheader = nil,
label1 = _CFG.parameter.name.label,
data1 = coreData.name and coreData.name or nil,
header1 = nil,
}
self:addOutput(require('Module:Infobox').infobox(ib_args))
return true
end
return false
end
function ClassName:addPageBody()
_debug(self, 1, 'entering ClassName:addPageBody(), from ' .. tostring(self))
_debug(self, 2, ' rendering errors and warnings and adding them to output')
local frame = mw.getCurrentFrame()
self:addOutput(self:renderErrors())
self:addOutput(self:renderWarnings())
if self:goodToGo() then
self:addOutput('No output yet')
return true
end
return false
end
function ClassName:myArgumentProcessing(coreData)
_debug(self, 1, 'entering ClassName:myArgumentProcessing(args) to process coreData, from ' .. tostring(self))
-- function that performs some individual transformation args --> coreData
-- remember: you can add warnings to your output with self:addWarning(warning). the page, however, will not be put in any gardening category. for that, use self:addError()
-- hint: for conversion bool values, this is useful: FoundationClass.myYesno
local coreData = coreData
return coreData -- this is your new coreData.
end
function ClassName:myDataAdjustments(data)
_debug(self, 1, 'entering ClassName:myDataAdjustments(data) to convert data from data store into data suitable for argument processing, from ' .. tostring(self))
-- function that performs some individual transformation datastore data into argument data
-- keep in mind, when using smw data store, that data is indexed by parameter names, not properties
-- hint: for conversion bool values, this is useful: FoundationClass.myYesno
local data = data
return data -- this is your new data table, being passed on to initFromArgs and subsequently to plausibility testing
end
function ClassName:myPlausibilityTest(args)
_debug(self, 1, 'entering ClassName: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
-- use self:addError(text); this also puts the page in its class's gardening category
return false -- return value will be ignored. but if you add any error, the object's initialization will fail with the error
end
function ClassName:myStashAdjustments(stash, storeType)
_debug(self, 1, 'entering ClassName:myStashAdjustments(stash) to do some minor adjustments on data before storing, from ' .. tostring(self))
-- function that alters the stash before storing the data. if necessary, you can complate skip storing this stash, if you return false or the empty table {}
-- storeType is the actual method of storage for this call. either 'cargo', or 'smw'
-- hint: for conversion bool values, this is useful: FoundationClass.myYesno
local stash = stash
return stash -- this is your new stash. this will be stored. it has format (fieldname: value)
end
function ClassName:method()
_debug(self, 1, 'entering ClassName:method() to do something, from ' .. tostring(self))
return true
end
return ClassName
|
class module's documentation page: |
---|
{{documentation subpage}} {{module rating|protected}} <!-- Categories go at the bottom of this page and interwikis go in Wikidata. --> 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 == {{code|lang=lua|code= local name = args[1] or args.name or mw.title.getCurrentTitle().rootText local Class = require('Module:Name/class') local me = Class:new(mw.title.getCurrentTitle().prefixedText) me:initFromArgs(args) me:storeData() me:addInfobox() me:addPageBody() return me:render() }} {{#invoke:Name|explainDataStore}} == Methods == === Constructor === ==== new(uid, superhandler) ==== Creates a new Object for the class. ;uid :variable, optional :used to identify the object ;superhandler :object of childclass of Foundationclass, optional :supply the superhandler, if you instanciate this object within another object. the instanciated object will pass errors and warnings to the superhandler and forgo adding the object category ;return :object, of the class === public methods === ==== addInfobox() ==== If no errors and data is present, adds an infobox to the object's output. {{small| ;return :boolean, whether adding was successful or not }} ==== addPageBody() ==== 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. {{small| ;return :boolean, whether adding was successful or not }} ==== myArgumentProcessing(coreData) ==== Performs the individual argument processing in [[#initFromArgs(args)|initFromArgs(args)]] right before inititializing it. {{small| ;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 }} ==== myDataAdjustments(data) ==== Performs a transformation form data (coming from the datastore) into data used for argument processing. This is called by [[#initFromData(data)|initFromData(data)]] (for smw: after property to parameter conversion) and is directly passed to [[#initFromArgs(args)|initFromArgs(args)]] and subsequently plausibility test. {{small| ;data :table, mandatory :a data table coming directly from the data store ;return :table, the new data table suiteable for argument processing }} ==== myPlausibilityTest(args) ==== Performs the individual plausibility tests in [[#initFromArgs(args)|initFromArgs(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)|addError(errortext)]]. {{small| ;args :table, mandatory :arguments passed to the template to be checked ;return :boolean, whether the object is plausible or not. }} ==== myStashAdjustments(stash, storeType) ==== Performs the adjusts the stash in [[#storeData()|storeData()]] right before storing it. {{small| ;stash :table, mandatory :the array of data to be saved (in the form fieldname: value) ;storeType :string, mandatory :type of storage method used with the current call (either 'cargo' or 'swm'). In case you use both stores and your stash adjustment differs with each of this methods ;return :boolean, the new stash }} === static methods === ==== ClassName:mySfDynamicFieldAttribute(fieldname, attribute, value) ==== For some semantic form fields there are attribute values, that are not static, thus can not be provided at forehand in the [[#Configuration Data|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. Note, that you can completely disable a form field with this when you return false on attribute "disable". {{small| ;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 Data|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 === ==== _debug(self, level, text) ==== Adds output to the internal debug log. {{small| ;self :object, me ;level :int; mandatory :debug level for the message ;text :string; mandatory :debug message text ;return :void }} == Properties == === static === See also [[#Static Properties|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! <ul> * 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 ** property_name, string, optional, if the parameter is to be stored in smw, add the property name here ** property_type, string, optional, if the parameter is to be stored in smw, add the property type here (defaults to page) ** 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 [https://www.mediawiki.org/wiki/Extension:TemplateData#Format 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 </ul> ;ClassName.publicStaticProperty :type, explanation ;_privateStaticProperty :type, explanation === private === 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)|_debug(self, level, text)]] == Configuration Data == This class holds its control data in [[Module:{{BASEPAGENAME}}/config]]. == Inheritance == '''Note:''' You still reference those either by self:publicMethod() or ClassName:staticMethod() and ClassName.staticProperty respectively! === Methods === {{MediaWiki:Classengine-content-documentation-methods}} === Static Properties === {{MediaWiki:Classengine-content-documentation-properties}} {{#invoke:Name|categorize}}<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox|| <!-- Note: the class engine sets the categories "Project modules" and "Lua class modules" automatically in categorize --> <!-- Categories go here if you wish an additional category to that set in {{module rating}} above automatically. --> }}</includeonly> |
class configuration (sample file): |
---|
local superglobal = mw.loadData( 'Module:Foundationclass/globalconfig' )
local form = {
enable = true, -- Do you want to create a form for this class? Note: When you don't want to have a form _page_, but need this to be a part of another form (as a holds-template form), set this to true!
name = '', -- The name of the form, i.e. the form will be placed an page [[Form:Formname]]. If you don't need an actual form page, leave this empty (e.g. if this is a prot of another form as holds-template or such).
teaserText = '', -- This is the text displayed on the form:name page (before you see the actual form))
typeCreateLink = 'none', -- This field lets you choose, what kind of object create link is provided to the user on the form page: is there none, a formlink, or a forminput field? possible values are: 'none' (default), 'forminput', 'formlink'
createInfotext = '', -- This is the short text that appears right above the input field. Short being the important part. Please limit yourself to a short sentence.
createInputPlaceholder = '', -- Placeholder text that is shwon in the form create input field
createInputQueryString = '', -- You can use this option to pass information to the form; this information generally takes the form of ''templateName[fieldName]=value''. It should look like a typical URL query string; an example would be "query string=namespace=User&User[Is_employee]=yes".
createLinkPageName = '', -- With this, you can have the name of the page created by the form to be set automatically. You can use any of the parameters ''<template-name[field-name]>'' or ''<unique number>''. The latter takes options start=x, unique, random, and a number (length of id string, default 6).
-- IMPORTANT: If you want to use the one step process with a createLinkPageName, you have to add the output if your class's sfGenerateFormInfoTag() in comments to your form page!!!
-- this is a workaround for a semantic forms bug. see https://phabricator.wikimedia.org/T123230 for more information
createLinkQueryString = '', -- You can use this option to pass information to the form; this information generally takes the form of ''templateName[fieldName]=value''. It should look like a typical URL query string; an example would be "query string=namespace=User&User[Is_employee]=yes".
createLinkType = 'plain', -- This field lets you choose, what kind of form link is used to link to the form page: is it a plain link or a button (with parameter submission via get or post), possible values are nil, 'plain', 'button', 'post button'
labelCreate = '', -- label for create entity
labelEdit = '', -- label for edit entity
headerText = '', -- this is the text displayed above the form
notification = '', -- this notification will be displayed above your form
sectionList = {}, -- if you want to have hl2 sections of text after the datafields and before the freetext, name them here. Use strings for names of section headlines
allowsFreeText = false, -- will the form have a free text field?
freeTextPreload = nil, -- when this is set your free text will have a preload=<freeTextPreload> statement. of course only when allowsFreeText is set to true
buttons = {'save', 'preview', 'changes', 'cancel'}, -- which buttons should appera below the form
fieldSize = 80, -- what is the default size= for the form fields
textareaAttributes = { -- the defaults for your textarea fields
cols = 80,
rows = 4,
autogrow = true,
editor = 'wikieditor', -- other values would be false or 'none'...
},
fieldOrder = {
-- the order in which the form fields appear. NOTE: a parameter not in this list, will not appear in the form!!
-- YOU HAVE TO FILL THIS TABLE! Put in here all parameters, that are used in the form, even if you have your own sfGenerateForm() implemented using a different table.
-- Reason: This is also be used in plausibility tests
'',
},
}
local global = {
cargoTable = '', -- if you use dataStore cargo, name the table here. if you do not name a table, no persistant cargo data will be stored for that class
category = '', -- the mediawiki category, the entity is placed into
delimiter = ',', -- see to it, that the delimiter is not a character, that will be encoded by mw.text.encode. CargoUtil.store encodes the data for security reasons
description = '', -- a short description of the entity. will be displayed on the template documentation page for example
entityTitle = '', -- generic title for the entity
gardeningCategory = superglobal.gardeningCategory, -- the category, objects with erroneous/inplausible data will be put into
namespace = '', -- if you put this entity on a special namespace, name it here. NOTE: You have to be precise. This is case sensitive. But omit the colon.
smwIsSubobject = false, -- when using datastore smw: is this stored as subobject (and not as normal data)?
smwUseStorage = true, -- if you use dataStore smw, set this to true if you actually want persistant smw data to be stored for that class
}
local parameter = {
-- this is your list of parameters. you put all data here, that you would like to handle
-- * parameters of your form (and thus your template)
-- * when you fill td_type, your parameter will be shown on the template documentation page
-- * when you add the parameter name to form.fieldOrder, it will be added to the form and processed in plausibility tests
-- * add also data, that you only want to store (omit these from form.fieldOrder and leave the sf table, probably best, to leave td_type unset, too).
-- * hint: if you need a row in your table as information, add pseudo parameter w/o entry in fieldOrder, w/o sf table, w/o td_type, and w/o cargo/property entries
name = {
cardinality = 'single|list',
cargo_hidden = false, -- takes no value. If set, the field is not listed in either Special:ViewTable or Special:Drilldown, although it is still queriable.
cargo_size = nil, -- for fields of type "Text", sets the size of this field, i.e. the number of characters; default is 300
cargo_type = '',
description = '',
label = '',
property_name = '', -- please use underscores (_) instead of spaces
property_type = '', -- possible values are: Annotation URI, Boolean, Code, Date, Email, Number, Page (default), Quantity, Telephone Number, Temperature, Text, URL
severity = 'mandatory|suggested',
sf = {
-- note: this list is incomplete. see [[Module:SFfield/config]] for a complete list of supported attributes
-- note also: mandatory, list, property and values are derived form fields "above" this table
-- IMPORTANT: If you want this to be a regular form parameter, you have to add this table. even, if you leave it empty.
-- also: keep in mind that a parameter appears in the form only if you add its name to form.fieldOrder above
cargo_field = '',
cargo_table = '',
class = '',
default = '',
default_filename = '',
existing_values_only = true,
hidden = true,
image_preview = true,
input_type = '',
mapping_cargo_field = '',
mapping_cargo_table = '',
mapping_template = '',
max_values = 0,
maxlength = 0,
placeholder = '',
restricted = '', -- e.g.: restricted = superglobal.restrictionRole,
show_on_select = {}, -- takes either a string (in case of input type checkbox) or a table. table must be of format "selected value" : "field shown"
size = 0,
unique = true,
unique_for_category = true,
unique_for_namespace = true,
uploadable = true,
values_dependent_on = '',
values_from_category = '',
values_from_namespace = '',
},
td_default = '',
td_type = '',
values = {},
},
}
local template = {
name = 'nameOfYourTemplate', -- the name of your template. e.g.: your template can be found on the page [[Template:nameOfYourTemplate]]
templateDocumentationSeeAlso = {'List', 'of', 'similar', 'or', 'related', 'templates'} -- used in the see also-section of your template documentation
}
return {
form = form,
global = global,
parameter = parameter,
template = template,
}
|
configuration documentation page: |
---|
{{documentation subpage}} {{module rating|protected}} <!-- Categories go at the bottom of this page and interwikis go in Wikidata. --> This module provides data for [[Module:Name/class]] == Usage == {{code|lang=lua|code=local cfg = mw.loadData('Module:Name/config')}} {{#invoke:Name|categorize}}<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox|| <!-- Note: The class engine sets the categories "Project modules" and "Lua class modules" automatically in function categorize --> <!-- Categories go here if you wish an additional category to that set in {{module rating}} above automatically. --> }}</includeonly> |
template: |
---|
{{#invoke:Name|main|{{BASEPAGENAME}}}}<noinclude> {{documentation}} </noinclude> |
template documentation page: |
---|
{{Documentation subpage}} <!-- Categories go at the bottom of this page. --> {{#invoke:Name|templateDocumentation}} {{#invoke:Name|categorize}}<includeonly>{{#ifeq:{{SUBPAGENAME}}|sandbox | | <!-- Note: The class engine sets the category "Project templates" automatically in function categorize --> <!-- ADD CATEGORIES AFTER THIS LINE --> }}</includeonly> |
form: | ||
---|---|---|
<noinclude>{{#invoke:Name|sfGenerateFormEntry}}{{#invoke:Name|categorize}}</noinclude> <includeonly>{{#invoke:Name|sfGenerateForm}}</includeonly> <!-- Note: The class engine sets category "Project forms" automatically in function categorize --> |
category: |
---|
{{#invoke:Name|categoryPage}}{{#invoke:Name|categorize}} <!-- Note: The class engine sets category "My Project" automatically in function categorize --> |
gardening category: |
---|
{{#invoke:Name|gardeningCategoryPage}}{{#invoke:Name|categorize}} <!-- Note: The class engine sets category "Project entities with erroneous input" automatically in function categorize --> |
private, public, class or instance
- | public | private |
---|---|---|
instance | function MyClass:publicMethod()
MyClass.publicProperty
|
local _privateMethod = function (self, var)
_private[self]._privateProperty
|
class | function MyClass.static:staticMethod()
MyClass.static.staticProperty
-- accessing
MyClass.staticProperty
-- being "outside":
MyClass:staticMethod()
-- being inside a static method
self:staticMethod()
-- being inside a public method
self.class:staticMethod()
|
local _privateMethod = function (self, var)
local _privateProperty
|
private
property
you can declare a property private in one of two ways:
- anywhere, preferably before your constructor, declare a
local var
to have a private propery, this is not recommended, but it allows you to declare a private property, that can be used by your static methods. thus being somewhat private static - for your instances, you can use the table _private[self] as a private store. it is available after your construrctor has been called (since this is an instance attribute)
method
a private method is declared thus:
. If you want to use the method in an public/static/other private method before it is declared (aka: the calling method is on a lower line number than your private method's declaration), decare it ahead and define it later:
local _privateMethod = function(self, var)
local _privateImportantMethod
..
privateImportantMethod = function(self, var)
private class and instance methods are basically the same.
public
property
can be dclared via class.property. DONT DO THIS. It is bad style!
method
Declare them class:publicMethod(var). They are, after all, public
NOTE: public methods can be called by an instance, but also as static method:
function Class:public()
return 'public: ' .. tostring(self)
end
local me = Class:new()
me.public() -- returns "public: Instance of class Class"
Class:public() -- returns "public: class Class"
static
property
Declare a static property like this: class.static.myProperty = 'Hello World'
. This produces a public property, that can be accessed by the class, childclasses or instances via *.myProperty (replace * with class, object, childclass, ...)
method
Much the same as static properties, but you should use the colon operator:
when definig the method. On accessig this method, you should use the dot-notation: function Class.static:staticMethod()
function Class.staticMethod(self)
NOTE: Other than public methods, they can only be called by the class, but not by an instance:
function Class.static:static()
return 'static: ' .. tostring(self)
end
local me = Class:new()
me.static() -- returns "error: attempt to call method 'static' (a nil value)"
Class:static() -- returns "static: class Class"
Class.static(self) -- this is not called via colon (:) operator as to preserve the childClass's scope when inheriting from this class
Methods
Constructor
Warning When you instantiate an object from another object, you have to supply the superhandler. Otherwise you might get categorized or defaultsorted! |
Warning If you want to be able to use initMyself(), then you have to submit the correct uid-value here. The method must be able to identify itself by this value! |
new(uid, superhandler)
Creates a new Object for the class.
- uid
- variable, suggested
- used to identify the object. defaults to mw.title.getCurrentTitle().prefixedText
- superhandler
- object of childclass of Foundationclass, optional
- supply the superhandler, if you instanciate an object within another object. the instanciated object will pass errors and warnings to the superhandler and forgo adding an object category
- return
- object, of the class
Abstract Methods
Warning You have to implement (thus overwriting) the following abstract methods in your childclass, otherwise the execution of most of your methods will fail! Take note: FoundationClass:mySfDynamicFieldAttribute(fieldname, attribute, value) is a static method, the rest must be declared public! |
myArgumentProcessing(coreData)
Performs the individual argument processing in initFromArgs(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
myDataAdjustments(data)
Performs a transformation form data (coming from the datastore) into data used for argument processing. This is called by initFromData(data) (for smw: after property to parameter conversion) and is directly passed to initFromArgs(args) and subsequently plausibility test.
- data
- table, mandatory
- a data table coming directly from the data store
- return
- table, the new data table suiteable for argument processing
myPlausibilityTest(args)
Performs the individual plausibility tests in initFromArgs(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(stash, storeType)
Can adjusts the stash in storeData() right before storing it.
- stash
- table, mandatory
- the array of data to be saved (in the form fieldname: value)
- storeType
- string, mandatory
- type of storage method used with the current call (either 'cargo' or 'swm'). In case you use both stores and your stash adjustment differs with each of this methods
- return
- table, the new stash
FoundationClass:mySfDynamicFieldAttribute(fieldname, attribute, value)
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. Note, that you can completely disable a form field with this when you return false on attribute "disable".
- 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)
Public methods
addCategory(category)
Prepares to add the page to category category. Note: until you actually call render() or renderCategories(), this will not be implemented
- category
- string, mandatory
- the name of the category, to add the page to
- return
- boolean, true
addError(errortext)
adds errortext as new error to the list of errors, rendered at a later time.
- errortext
- string, mandatory
- text added to list of errors
- return
- boolean, whether adding was successful or not
addInfobox()
If no errors and data is present, adds an infobox to the object's output. NOTE: This is a shell method and should be overwritten!
- return
- boolean, whether adding was successful or not
addOutput(content)
Adds something to the page's output. Something can be of type string, int, or table (that needs to have __tostring() implemented)
- content
- string, int, or table; mandatory
- content element that is added to page's output
- return
- boolean, whether adding was successful or not
addPageBody()
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. NOTE: This is a shell method and should be overwritten!
- return
- boolean, whether adding was successful or not
addWarning(warning)
adds warning as new warning to the list of warnings, to be rendered at a later time (with renderWarnings()).
- warning
- string, mandatory
- text added to list of warnings
- return
- boolean, whether adding was successful or not
getCoreData()
Returns the table of coreData
- return
- table, the value for _private[self].coreData, emtpy if not initialized
getUid()
Returns the object's uid, nil if not set
- return
- variable, the value for _private[self].uid
goodToGo()
Is this a proper object (with data and no errors)
- return
- boolean, whether we are proper initialized
initFromArgs(args)
Initializes the object with a data table, containing arguments (template parameter). Does plausibility tests and mangling of input and either fills list of errors or adds input to the object's data. {{{1}}}
initFromData(data)
Initializes the object with a data table, coming from the datastore. Depending on datastore, that means that the table keys might be different than when using arguments form the template. Does plausibility tests and mangling of input and either fills list of errors or adds input to the object's data. {{{1}}}
initMyself(uid)
Initializes the object with data from the data store. The method queries for the object's uid in the container defined by Foundationclass.globalConfig.uidFieldName (can be set to an infividual name in Module:Foundationclass/globalconfig) in either the class's table (in case of datastore cargo) or for objects that have Foundationclass.globalConfig.smwClassProperty set to class.name (in case of datastore smw). The uid was either passed to the method (priority) or submitted to the constructor. Does NOT do plausibility tests and mangling of input but assumes the data comes directly from the data store and thus can be trusted (i.e. passes _plausibilityTest())
- uid
- string, optional
- the data, the object can use to identify itself. This field can be omitted, in which case the uid that was submitted to the constructor will be used.
- return
- boolean, whether initialization was successful or not
render()
Renders the object's output
- return
- string, the textual representation of the object (which can vary, depending on what add*-methods you called before)
renderCategories()
Renders the object's categories (if any), thus adding them to the output stream and in turn sorting the page in it, if and only if render() is called on the object's page (when self:getUid == Foundationclass/doc).
- return
- object of type mw.html, the wikitext necessary to add the page to the categories
renderErrors()
Renders the object's errors (if any)
- return
- object of type mw.html, the representation of the list of errors
renderWarnings()
Renders the object's warnings (if any)
- return
- object of type mw.html, the representation of the list of warnings
setSortkey(sortkey)
Sets a default sortkey for this page using the magic word DEFAULTSORT. Only applies, if no superhandler is given.
- sortkey
- string, mandatory
- new sortkey for this page
- return
- void
setUid(value)
Sets my uid to the given value. normally this should be set by constructor
- value
- string/integer, mandatory
- new valued for my uid
- return
- boolean, true/false
storeData()
If this was initialized with outside data and there are no errors, stores the arguments in an appropriate data store (smw or cargo). In case of cargo, also calls the necessary #cargo_declare parser function if in the template namespace.
- return
- boolean, whether store was successful or not
Static methods
FoundationClass:categorize()
Placed on one to class's pages (usually not on the class object pages), this calculates the necessary (meta-) category, to put the page in, using pagetitle, subpagetitle, namespace, and so on. Your project's categories (defined in Module:Foundationclass/globalconfig) are used.
- return
- string, to be put on page, so that it will be categorized
FoundationClass:categoryPage()
Procudes the output for our corresponding category page. Including the message box and the display of the data structure.
- return
- object of type mw.html, the representation of the category page's content
FoundationClass:cargoGenerateTableStructure()
Produces a cargo table declaration array (fieldname => declaration of field) that can be used in method storeData() for cargo_declare.
- return
- table, data structure for cargo table
FoundationClass:explainDataStore()
Produces a textual explanation of the used datastructure (table definition for cargo or property list and types for smw) that can be printed on various dodumentation pages
- return
- string, a textual explanation
FoundationClass:formRedlink(target, form, linktext, queryString)
Takes a pagename (target) and a formname (form) and then generates a link to that page if the page exists. Otherwise it links to the form to create the page. Linktext is target per default, if you do not provide linktext
- target
- string, mandatory
- the pagename (including namespace) to link to
- form
- string, mandatory
- the name of the form (w/o the form namespace!!) to fallback to, if page does not exist
- linktext
- string, optional
- text you want to display instead of target
- queryString
- string, optional
- the query string provided to the form, e.g.
'Template[page]=' .. mw.title.getCurrentTitle().prefixedText
- return
- string, the requested link
FoundationClass:gardeningCategoryPage()
Procudes the output for the class' gardening category page (if any). Includung the message boxes.
- return
- object of type mw.html, the representation of the gardening category page's content
FoundationClass:mwLink(object)
Takes object and links it (adding square brackets). If object is a table, it iterates over it with lua's mw.text.listToText()
- object
- mixed
- object to return as linked string(s)
- return
- string, with all elements of object mw-linked
FoundationClass:sfGenerateForm()
Generates all output necessary for a form, that can be used to create or maintain an object of this class. Note: this output is to be put inside the <includeonly>-tag on the Form page.
- return
- object of class mw.html, the representation of the form
FoundationClass:sfGenerateFormEntry()
Generates the "teaser" text shown on the form page when accessing it to create a form (before you type in the name in the input field)
- return
- object of class mw.html, the representation of the form teaser
FoundationClass:sfGenerateFormInfoTag()
Generates a form's info-tag, together with create and edit title and - if applicable - the query string (in case we have createLinkType formlink).
- return
- string, a semantic form info tag
FoundationClass:sfGenerateFormLink()
Generates a form input field or a form link that links to the class's form (essentially calls the parser function #forminput or #formlink respectively).
- return
- string, the input field, that lints to the form
FoundationClass:sfGenerateFormTable(fieldlist)
Generates a table that can be used in a form inside the {{{for template}}} tag. The table contains all fields, that are named in the table parameter fieldlist (which defaults to _CFG.form.fieldOrder) and that are present in _CFG.parameter.. All fields with attribute hidden are placed after the closing /table-tag
- fieldlist
- table, optional
- contains a list of fieldnames, to be processed and added to the return node.
- return
- object of class mw.html, the representation of the formtable
FoundationClass:sfInitField(fieldname)
Creates a field object of Class SFfield and initializes it per myConfiguration.parameters[fieldname] if entry is present
- fieldname
- string, mandatory
- contains the name of the field to initialize
- return
- object of Class SFfield, the initialized field object. nil if fieldname is not present in parameter-array
FoundationClass:smwGetProperty2ParameterTranslationTable()
Returns a translation table property-name => parametername, if data store smw is used.
- return
- table, for every property used in the class the corresponding parameter name
FoundationClass:templateDocumentation()
Generates almost all the output, necessary to have a good documentation page for the corresponding template. Only missing the {{documentation subpage}} call at the top and the includeonly part at the bottom.
- return
- object of class mw.html, the representation of the template documentation
FoundationClass:usesDataStore(store)
Returs true, if class uses store as datastore. Available stores are 'cargo' and 'smw'
- store
- string, mandatory
- store type to check against
- return
- bool, whether store store is used as data store
private methods
These private Methods can not be used by child classes!
_amIPlausible(self)
Returs true or false, whether the object is plausible or not (i.e. has no errors or 1+)
- self
- object, me
- return
- boolean, whether the object is plausible or not
_debug(self, level, text)
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
_plausibilityTest(self, args)
Checks, if input provided via template is plausible enough, to represent the object (to be stored and displayed). Also fills the list of errors and does some argument preparation.
- self
- object, me
- args
- table, mandatory
- arguments passed to the template to be checked
- return
- boolean, whether the object is plausible or not
Properties
static
- FoundationClass.globalConfig
- table, holds some global configuration (data, that applies to all classes the same way). See Module:Foundationclass/globalconfig for details.
- FoundationClass.myCargoUtil
- table, instance of Module:CargoUtil
- FoundationClass.mySwmUtil
- table, instance of Module:SmwUtil
- FoundationClass.myTableTools
- table, instance of Module:TableTools
- FoundationClass.myYesno
- table, instance of Module:Yesno
private
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.
- categories
- table, holds the objects categories
- coreData
- table, holds the objects data ofter initializing
- dbg
- object, my instance of Module:Debug/class for debugging purposes
- errors
- table, a list of errors that occurred
- fullpagename
- string, name of currentpage including namespace
- initialized
- boolean, is this object properly initialized
- loadedDataFromDataStore
- boolean, did this object get its data from the data store
- output
- object of type mw.html, holds all output to be rendered()
- pagename
- string, name of current page (or current page's super page) w/o namespace
- uid
- string, uinique identifier ('NIL' if unset)
- warnings
- table, a list of warnings that came up
Configuration Data
This class holds gets its control data from the child class. Also, there is some global configuration data in Module:Foundationclass/globalconfig, that applies to all classes.
Dependencies
If you want to use Module:Foundationclass, you also need the following items (and their doc pages!):
- Module:Middleclass
- Module:Foundationclass/config
- Module:Foundationclass/classDoc
- Module:Foundationclass/globalconfig
- Module:CargoUtil and Extension:Cargo if you want to use it as a data store
- Module:SmwUtil and Extension:Semantic MediaWiki if you want to use it as a data store
also
- Module:Arguments
- Module:Collapse
- Module:Debug/class
- Module:Error
- Module:Infobox
- Module:Lua banner
- Module:Message box
- Module:SFfield
- Module:SFfield
- Module:TableTools
- Module:Yesno
- {{code}}
- Extension:TemplateData
and of course Extension:Semantic Forms
Also, have a look at the extended functionality of the Class engine.
Interface messages
To generate the Useful_templates, Foundationclass makes use of the following interface messages:
- MediaWiki:Classengine-content-documentation-methods
- MediaWiki:Classengine-content-documentation-properties
- MediaWiki:Classengine-template-module-page
- MediaWiki:Classengine-template-module-documentation-page
- MediaWiki:Classengine-template-module-class-page
- MediaWiki:Classengine-template-module-class-documentation-page
- MediaWiki:Classengine-template-module-config-documentation-page
- MediaWiki:Classengine-template-template-page
- MediaWiki:Classengine-template-template-documentation-page
- MediaWiki:Classengine-template-form-page
- MediaWiki:Classengine-template-category-page
- MediaWiki:Classengine-template-gardeningcategory-page
- MediaWiki:Classengine-template-property-page
Next in dev queue
- have foundation class try to detect integer inputs (by td_type or cargo_type) and run a regexp in _plausibilityTest
- have foundationclass use mw message system for printouts instead of hardcoded text
- a template or page, that #autogenerates all categories, defined in Module:Foundationclass/globalconfig